home *** CD-ROM | disk | FTP | other *** search
- From wietse@wzv.win.tue.nl Wed Mar 24 23:37:23 1993
- Received: from svin01.win.tue.nl by svbs01.bs.win.tue.nl (4.1/1.45)
- id AA16728; Wed, 24 Mar 93 23:37:23 +0100
- Received: from svin09.info.win.tue.nl by svin01.win.tue.nl (4.1/1.45)
- id AA00471; Wed, 24 Mar 93 23:37:18 +0100
- Received: from wzv.win.tue.nl by svin09.info.win.tue.nl (4.1/1.45)
- id AA02366; Wed, 24 Mar 93 23:33:04 +0100
- Received: by wzv.win.tue.nl (4.1/1.45)
- id AA01314; Wed, 24 Mar 93 23:06:25 +0100
- Date: Wed, 24 Mar 93 23:06:25 +0100
- From: wietse@wzv.win.tue.nl (Wietse Venema)
- Message-Id: <9303242206.AA01314@wzv.win.tue.nl>
- To: ecd@cert.org
- Subject: tcp wrapper reveals SunOS 4.x kernel bug
- Cc: wswietse@win.tue.nl
- Status: OR
-
- The new wrapper release causes occasional kernel panics with SunOS 4.x.
- There is a bug in the getsockopt() system call implementation.
-
- Getsockopt() was used to detect source-routing attacks. That code was
- enabled by default. I have changed this: by default the code no longer
- tries to expose source-routing attacks.
-
- The result of this effort is below. Changes were made only to the
- documentation, to the Makefile, and to the patchlevel.h file.
-
- Please replace the wrapper archives on cert.org. I will post a separate
- message to the cert-tools mailing list.
-
- Wietse
- --------------
-
- With the programs that come with this kit you can monitor incoming
- requests for IP services such as TFTP, EXEC, FTP, RSH, TELNET, RLOGIN,
- FINGER, SYSTAT, and many others.
-
- Optional features are: access control based on pattern matching; remote
- username lookup using the RFC 931 protocol; protection against attacks
- from hosts that pretend to have someone elses name; protection against
- attacks from hosts that pretend to have someone elses network address.
-
- The programs can be installed without requiring any changes to existing
- software or configuration files. By default, they just log the remote
- host name and do some sanity checks on the origin the request. No
- information is exchanged with the remote client process.
-
- The most notable differences with respect to the previous release are:
-
- - Optional protection against attacks from hosts that pretend to
- have someone elses network address. For example, the address of a
- trusted host within your own network.
-
- - The access control language has been extended with a simple but
- powerful operator that greatly simplifies the design of rule sets
- (ALL: .foo.edu EXCEPT dialup.foo.edu). Blank lines are permitted,
- and long lines can be continued with backslash-newline.
-
- - All configurable stuff, including path names, has been moved into
- the Makefile so that you no longer have to hack source code to just
- configure the programs.
-
- - Ported to Solaris 2. TLI-based applications not yet supported.
- Several workarounds for System V bugs.
-
- - A small loophole in the netgroup lookup code was closed, and the
- remote username lookup code was made more portable.
-
- - Still more documentation. The README file now provides tutorial
- sections with introductions to client, server, inetd and syslogd.
-
- The default mode of operation should be backwards compatible with
- earlier versions.
-
- Wietse Venema (wietse@wzv.win.tue.nl),
- Department of Mathematics and Computing Science,
- Eindhoven University of Technology,
- The Netherlands.
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: README miscd.c tcpd.c fromhost.c hosts_access.c
- # shell_cmd.c log_tcp.h try.c refuse.c Makefile.dist hosts_access.5
- # strcasecmp.c BLURB rfc931.c tcpd.8 hosts_info.c hosts_access.3
- # hosts_ctl.c percent_x.c options.c clean_exit.c setenv.c
- # patchlevel.h strtok.c fix_options.c inet_addr_fix
- # Wrapped by wietse@wzv on Wed Mar 24 22:44:58 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f README -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"README\"
- else
- echo shar: Extracting \"README\" \(34888 characters\)
- sed "s/^X//" >README <<'END_OF_README'
- X@(#) README 1.10 93/03/24 22:42:46
- X
- X
- XTable of contents
- X-----------------
- X
- X 1 - Introduction
- X 2 - Disclaimer
- X 3 - Tutorials
- X 3.1 - How it works
- X 3.2 - Where the logging information goes
- X 4 - Features
- X 4.1 - Access control
- X 4.2 - Host name spoofing
- X 4.3 - Host address spoofing
- X 4.4 - Remote username lookups
- X 4.5 - Language extension hooks
- X 5 - Other works
- X 5.1 - Related documents
- X 5.2 - Related software
- X 6 - Limitations
- X 6.1 - Known wrapper limitations
- X 6.2 - Known system software bugs
- X 7 - Configuration and installation
- X 7.1 - Easy configuration and installation
- X 7.2 - Advanced configuration and installation
- X 7.3 - Daemons with arbitrary path names
- X 7.4 - Building and testing the access control rules
- X 7.5 - Other applications
- X 8 - Acknowledgements
- X
- X1 - Introduction
- X----------------
- X
- XWith this package you can monitor incoming connections to the SYSTAT,
- XFINGER, FTP, TELNET, RLOGIN, RSH, EXEC, TFTP, TALK, and other network
- Xservices.
- X
- XThe package provides tiny daemon wrapper programs that can be installed
- Xwithout any changes to existing software or to existing configuration
- Xfiles. The wrappers report the name of the remote host and of the
- Xrequested service; the wrappers do not exchange information with the
- Xremote client process, and impose no overhead on the actual
- Xcommunication between the client and server applications.
- X
- XOptional features are: access control to restrict what systems can
- Xconnect to your network daemons; remote user name lookups with the RFC
- X931 protocol; additional protection against hosts that pretend to have
- Xsomeone elses host name; additional protection against hosts that
- Xpretend to have someone elses host address.
- X
- XEarly versions of the programs were tested with Ultrix >= 2.2, with
- XSunOS >= 3.4 and ISC 2.2. Later versions have been installed on a wide
- Xvariety of platforms such as SunOS 4.x and 5.x, Ultrix 3.x and 4.x, DEC
- XOSF/1 T1.2-2, HP-UX 8.x, AIX 3.1.5, Apollo SR10.3.5, Sony, NeXT, SCO
- XUNIX, DG/UX, Cray, and an unknown number of other ones.
- X
- XRequirements are that the network daemons are spawned by a super server
- Xsuch as the inetd; a 4.3BSD-style socket programming interface; and the
- Xavailability of a syslog(3) library and of a syslogd(8) daemon. The
- Xwrappers should run without modification on any system that satisfies
- Xthese requirements. Workarounds have been implemented for several
- Xcommon bugs in systems software.
- X
- XWhat to do if this is your first encounter with the wrapper programs:
- X1) read the tutorial sections for an introduction to the relevant
- Xconcepts and terminology; 2) glance over the security feature sections
- Xin this document; 3) follow the installation instructions (easy or
- Xadvanced). I recommend that you first use the default security feature
- Xsettings. Run the wrappers for a few days to become familiar with
- Xtheir logs, before doing anything drastic such as cutting off access or
- Xinstalling booby traps.
- X
- X2 - Disclaimer
- X--------------
- X
- XThe wrapper programs rely on source address information obtained from
- Xnetwork packets. Such information is not 100 percent reliable, although
- Xthe wrappers do their best to expose forgeries.
- X
- XIn the absence of cryptographic protection of message contents, and of
- Xcryptographic authentication of message originators, all data from the
- Xnetwork should be treated with sound scepticism.
- X
- XTHIS RESTRICTION IS BY NO MEANS SPECIFIC TO THE TCP/IP PROTOCOLS.
- X
- X3 - Tutorials
- X-------------
- X
- XThe tutorial sections give a gentle introduction to the operation of
- Xthe wrapper programs, and introduce some of the terminology that is
- Xused in the remainder of the document: client, server, the inetd and
- Xsyslogd daemons, and their configuration files.
- X
- X3.1 - How it works
- X------------------
- X
- XAlmost every application of the TCP/IP protocols is based on a client-
- Xserver model. For example, when a user invokes the telnet command to
- Xconnect to one of your systems, a telnet server process is executed on
- Xthe target host. The telnet server process connects the user to a login
- Xprocess. A few examples of client and server programs are shown in the
- Xtable below:
- X
- X client server application
- X --------------------------------
- X telnet telnetd remote login
- X ftp ftpd file transfer
- X finger fingerd show users
- X
- XThe usual approach is to run one single daemon process that waits for
- Xall kinds of incoming network connections. Whenever a connection is
- Xestablished, this daemon (usually called inetd) runs the appropriate
- Xserver program and goes back to sleep, waiting for other connections.
- X
- XThe wrapper programs rely on a simple, but powerful mechanism. Instead
- Xof directly running the desired server program, the inetd is tricked
- Xinto running a small wrapper program. The wrapper logs the remote host
- Xname or address and performs some additional checks. When all is well,
- Xthe wrapper executes the desired server program and goes away.
- X
- XThe wrapper programs have no interaction with the remote user (or
- Xclient process). This has two major advantages: 1) the wrappers are
- Xapplication-independent, so that the same program can protect many
- Xkinds of network services; 2) no interaction also means that the
- Xwrappers are invisible from outside (at least for regular users).
- X
- XAnother important property is that the wrapper programs are active only
- Xwhen the initial contact between client and server is established. Once
- Xa wrapper has done its work there is no overhead on the client-server
- Xcommunication.
- X
- XThe simple mechanism has one major drawback: since the wrappers go away
- Xafter the initial contact between client and server processes, the
- Xwrappers are of little use with network daemons that service more than
- Xone client. The wrappers would only see the first client attempt to
- Xcontact such a server. The NFS mount daemon is a typical example of
- Xa daemon that services requests from multiple clients.
- X
- XThere are two ways to use the wrapper programs:
- X
- X1) The easy way: move network daemons to some other directory and fill
- X the resulting holes with copies of the wrapper programs. This
- X approach involves no changes to configuration files, so there is
- X very little risk of breaking things.
- X
- X2) The advanced way: leave the network daemons alone and modify the
- X inetd configuration file. For example, an entry such as:
- X
- X tftp dgram udp wait root /usr/etc/tcpd in.tftpd -s /tftpboot
- X
- X When a tftp request arrives, inetd will run the wrapper program
- X (tcpd) with a process name `in.tftpd'. This is the name that the
- X wrapper will use when logging the request and when scanning the
- X optional access control tables. `in.tftpd' is also the name of the
- X server program that the wrapper will attempt to run when all is
- X well. Any arguments (`-s /tftpboot' in this particular example) are
- X transparently passed on to the server program.
- X
- XFor an account of the history of the wrapper programs, with real-life
- Xexamples, see the section below on related documents.
- X
- X3.2 - Where the logging information goes
- X----------------------------------------
- X
- XThe wrapper programs send their logging information to the syslog
- Xdaemon (syslogd). The disposition of the wrapper logs is determined by
- Xthe syslog configuration file (usually /etc/syslog.conf). Messages are
- Xwritten to files, to the console, or are forwarded to a @loghost.
- X
- XOlder syslog implementations (still found on Ultrix systems) only
- Xsupport priority levels ranging from 9 (debug-level messages) to 0
- X(alerts). All logging information of the same priority level (or more
- Xurgent) is written to the same destination. In the syslog.conf file,
- Xpriority levels are specified in numerical form. For example,
- X
- X 8/usr/spool/mqueue/syslog
- X
- Xcauses all messages with priority 8 (informational messages), and
- Xanything that is more urgent, to be appended to the file
- X/usr/spool/mqueue/syslog.
- X
- XNewer syslog implementations support message classes in addition to
- Xpriority levels. Examples of message classes are: mail, daemon, auth
- Xand news. In the syslog.conf file, priority levels are specified with
- Xsymbolic names: debug, info, notice, ..., emerg. For example,
- X
- X mail.debug /var/log/syslog
- X
- Xcauses all messages of class mail with priority debug (or more urgent)
- Xto be appended to the /var/log/syslog file.
- X
- XBy default, the wrapper logs go to the same place as the transaction
- Xlogs of the sendmail daemon. The disposition can be changed by editing
- Xthe Makefile and/or the syslog.conf file. Send a `kill -HUP' to the
- Xsyslogd after changing its configuration file. Remember that syslogd,
- Xjust like sendmail, insists on one or more TABs between the left-hand
- Xside and the right-hand side expressions in its configuration file.
- X
- X4 - Features
- X------------
- X
- X4.1 - Access control
- X--------------------
- X
- XWhen compiled with -DHOSTS_ACCESS, the wrapper programs support a
- Xsimple form of access control. Access can be controlled per host, per
- Xservice, or combinations thereof. The software provides hooks for the
- Xexecution of shell commands when an access control rule fires; this
- Xfeature may be used to install "booby traps". For details, see the
- Xhosts_access.5 manual page, which is in `nroff -man' format. A later
- Xsection describes how you can test your access control rules.
- X
- XAccess control is enabled by default. It can be turned off by editing
- Xthe Makefile, or by providing no access control tables. The install
- Xinstructions below describe the Makefile editing process.
- X
- X4.2 - Host name spoofing
- X------------------------
- X
- XWith some network applications, such as RSH or RLOGIN, the remote host
- Xname plays an important role in the authentication process. Host name
- Xinformation can be reliable when lookups are done from a _local_ hosts
- Xtable, provided that the client IP address can be trusted.
- X
- XWith _distributed_ name services, authentication schemes that rely on
- Xhost names become more problematic. The security of your system now may
- Xdepend on some far-away DNS (domain name server) outside your own
- Xcontrol. Paradoxically, running NIS (YP) can actually improve hostname
- Xsecurity because it provides you with the equivalent of a local hosts
- Xfile.
- X
- XThe wrapper programs verify the remote host name that is returned by
- Xthe address->name DNS server, by asking for a second opinion. To this
- Xend, the programs look at the name and addresses that are returned by
- Xthe name->address DNS server. If any discrepancies are found, the
- Xwrappers conclude that at least one of the two name servers is lying,
- Xand assume that they are dealing with a host that pretends to have
- Xsomeone elses host name.
- X
- XWhen the wrappers are unable to verify the remote host name (the
- Xaddress->name lookup succeeds but the name->address lookup fails), they
- Xalso assume that the host name is wrong.
- X
- XWhen the remote host name is unavailable (the address->name lookup
- Xfails) the wrappers just use the remote host address when logging the
- Xconnection and when consulting the optional access control tables.
- X
- XWhen the sources are compiled with -DPARANOID, the wrappers will drop
- Xthe connection in case of a host name/address mismatch. When the
- Xsources are not compiled with -DPARANOID, the wrappers just pretend
- Xthat the host name is unknown when logging the connection and when
- Xconsulting the optional access control tables.
- X
- XParanoid mode is enabled by default. It can be turned off by editing
- Xthe Makefile. The configuration and installation below describes the
- XMakefile editing process.
- X
- X4.3 - Host address spoofing
- X---------------------------
- X
- XWhile host name spoofing can be found out by asking a second opinion,
- Xit is much harder to find out that a host claims to have someone elses
- Xnetwork address. And since host names are deduced from network
- Xaddresses, address spoofing is at least as effective as name spoofing.
- X
- XThe wrapper programs can give additional protection against hosts that
- Xclaim to have an address that lies outside their own network. For
- Xexample, some far-away host that claims to be a trusted host within
- Xyour own network. Such things are possible even while the impersonated
- Xsystem is up and running.
- X
- XThis additional protection is not an invention of my own; it has been
- Xpresent for at least five years in the BSD rsh and rlogin daemons.
- XUnfortunately, that feature was added *after* 4.3 BSD came out, so that
- Xvery few, if any, UNIX vendors have adopted it. Our site, and many
- Xother ones, has been running these enhanced daemons for several years,
- Xand without any ill effects.
- X
- XWhen the programs are compiled with -DKILL_IP_OPTIONS, source routing
- Xwill be disabled for all TCP connections that are handled by the
- Xwrapper programs.
- X
- XAll this cannot be used with SunOS 4.x because of a kernel bug in the
- Ximplementation of the getsockopt() system call. Kernel panics have been
- Xreported for SunOS 4.1.1 and SunOS 4.1.2. The symptoms are "BAD TRAP"
- Xand "Data fault" while executing the tcp_ctloutput() kernel function.
- X
- XThe feature is disabled by default. It can be turned on by editing the
- XMakefile. The configuration and installation section below describes
- Xthe Makefile editing process.
- X
- XUDP services do not benefit from this additional protection. With UDP,
- Xall you can be certain of is the network packet's destination address.
- X
- X4.4 - Remote username lookups
- X-----------------------------
- X
- XThe protocol proposed in RFC 931 provides a means to get the remote
- Xuser name from the client host. The requirement is that the client
- Xhost runs an RFC 931-compliant daemon. The information provided by such
- Xa daemon is not intended to be used for authentication purposes, but it
- Xcan provide additional information about the owner of a TCP connection.
- X
- XRemote user name lookups are enabled when the wrappers are compiled
- Xwith -DRFC931. There are some limitations: the number of hosts that
- Xrun an RFC 931 (or compatible) daemon is small (but growing); remote
- Xuser name lookups do not work for datagram (UDP) connections. More
- Xseriously, remote user name lookups can cause noticeable delays with
- Xconnections from non-UNIX PCs. The wrappers use a 30-second timeout for
- XRFC931 lookups, to accommodate slow networks and slow hosts.
- X
- XBy default, remote username lookups are not enabled. You can enable
- Xthem by editing the Makefile. The remote username lookup timeout period
- X(30 seconds default) can also be changed by editing the Makefile. The
- Xinstallation sections below describe the Makefile editing process.
- X
- XThe RFC 931 protocol has diverged into different directions (IDENT and
- XTAP). To add to the confusion, both protocols use the same network
- Xport. The daemon wrappers implement a common subset of the protocols.
- X
- X4.5 - Language extension hooks
- X------------------------------
- X
- XThe wrappers sport only a limited number of features. This is for a
- Xgood reason: programs that are run at high privilege levels must be
- Xeasy to verify.
- X
- XHowever, some sites have very specific needs. The options.c file
- Xprovides a framework for adding extensions to the access control
- Xlanguage. It comes with sample extensions that: (1) switch to another
- Xuser or group id; (2) perform remote user name lookups; (3) run an
- Xalternate server program (this allows you to produce customized bounce
- Xmessages or to do really nasty stuff); (4) set arbitrary environment
- Xvariables; (5) change the default file protection mask.
- X
- XThe language extension hook is not enabled by default because it
- Xintroduces an incompatible change to the access control language
- Xsyntax. Instructions to enable the extensions are given in the
- XMakefile.
- X
- X5 - Other works
- X---------------
- X
- X5.1 - Related documents
- X-----------------------
- X
- XThe war story behind the wrapper tools is described in:
- X
- X W.Z. Venema, "TCP WRAPPER, network monitoring, access control and
- X booby traps", UNIX Security Symposium III Proceedings (Baltimore),
- X September 1992.
- X
- X ftp.win.tue.nl:/pub/security/tcp_wrapper.ps.Z (postscript)
- X ftp.win.tue.nl:/pub/security/tcp_wrapper.txt.Z (flat text)
- X
- XThe same cracker is also described in:
- X
- X W.R. Cheswick, "An Evening with Berferd, In Which a Cracker is
- X Lured, Endured, and Studied", Proceedings of the Winter USENIX
- X Conference (San Francisco), January 1992.
- X
- X research.att.com:/dist/internet_security/berferd.ps
- X
- X5.2 - Related software
- X----------------------
- X
- XNetwork daemons etc. with enhanced logging capabilities can generate
- Xmassive amounts of information: our 100+ workstations generate several
- Xhundred kbytes each day. egrep-based filters can help to suppress some
- Xof the noise. A more powerful tool is the Swatch monitoring system by
- XStephen E. Hansen and E. Todd Atkins. Swatch can process log files in
- Xreal time and can associate arbitrary actions with patterns; its
- Xapplications are by no means restricted to security. Swatch is
- Xavailable from sierra.stanford.edu, directory /pub/sources.
- X
- XSocks, described in the UNIX Security III proceedings, can be used to
- Xcontrol network traffic from hosts on an internal network, through a
- Xfirewall host, to the outer world. Socks consists of a daemon that is
- Xrun on the firewall host, and of a library with routines that redirect
- Xapplication socket calls through the firewall daemon. Socks is
- Xavailable from s1.gov in /pub/socks.tar.Z.
- X
- XVersions of rshd and rlogind, modified to report the remote user name
- Xin addition to the remote host name, are available for anonymous ftp
- X(ftp.win.tue.nl:/pub/security/logdaemon-2.tar.Z). These programs are
- Xdrop-in replacements for SunOS 4.x, Ultrix 4.x, and SunOS 5.x.
- X
- XThe securelib shared library by William LeFebvre can be used to control
- Xaccess to network daemons that are not run under control of the inetd,
- Xsuch as the RPC daemons that run until the machine goes down.
- XAvailable from eecs.nwu.edu, file /pub/securelib.tar.
- X
- XWhere shared libraries or router-based packet filtering are not an
- Xoption, an alternative portmap daemon can help to improve RPC security,
- Xin particular that of NFS and of the NIS (YP) information service.
- Xftp.win.tue.nl:/pub/security/portmap.shar.Z was tested with SunOS 4.1.1
- Xand 4.1.2, Ultrix 3.0 and Ultrix 4.x, HP-UX 8.x and AIX. The protection
- Xis less effective than that of the securelib library because portmap is
- Xmostly a dictionary service. SunOS 4.x users should install the latest
- Xrevision of the portmap and NIS daemons instead, or adopt NIS+ which
- Xhas access control built in.
- X
- XSource for a portable RFC 931 (TAP, IDENT)-compatible daemon by Peter
- XEriksson is available from ftp.lysator.liu.se:/pub/ident/servers.
- X
- XSome TCP/IP implementations come without syslog library. Some come with
- Xthe library but have no syslog daemon. A replacement can be found in
- Xftp.win.tue.nl:/pub/security/surrogate-syslog.tar.Z. The fakesyslog
- Xlibrary that comes with the nntp sources reportedly works well, too.
- X
- X6 - Limitations
- X---------------
- X
- X6.1 - Known wrapper limitations
- X-------------------------------
- X
- XSome UDP (and RPC) daemons linger around for a while after they have
- Xserviced a request, just in case another request comes in. In the
- Xinetd configuration file these daemons are registered with the `wait'
- Xoption. Only the request that started such a daemon will be seen by the
- Xwrappers. This restriction does not apply to connection-oriented (TCP)
- Xservices.
- X
- XTLI (transport level interface), the System V stream-based and
- Xprotocol-independent network programming interface, is not yet
- Xsupported, but we're working on it.
- X
- XThe wrappers do not work with RPC services over TCP. These services are
- Xregistered as rpc/tcp in the inetd configuration file. The only non-
- Xtrivial service that is affected by this limitation is rexd, which is
- Xused by the on(1) command. This is no great loss. On most systems,
- Xrexd is less secure than a wildcard in /etc/hosts.equiv.
- X
- XRPC broadcast requests (for example: rwall, rup, rusers) always appear
- Xto come from the responding host. What happens is that the client
- Xbroadcasts its request to all portmap daemons on its network; each
- Xportmap daemon forwards the request to its own system. As far as the
- Xrwall etc. daemons know, the request comes from the local host.
- X
- XPortmap and RPC (e.g. NIS and NFS) security is a topic in itself. See
- Xthe section in this document on related software.
- X
- X6.2 - Known system software bugs
- X--------------------------------
- X
- XWorkarounds have been implemented for several bugs in system software.
- XThey are described in the Makefile. Unfortunately, some system software
- Xbugs cannot be worked around. The result is loss of functionality.
- X
- XOlder ConvexOS versions come with a broken recvfrom(2) implementation.
- XThis makes it impossible for the daemon wrappers to look up the
- Xremote host address (and hence, the name) in case of UDP requests.
- XA patch is available for ConvexOS 10.1; later releases should be OK.
- X
- XOn some systems, the optional RFC 931 remote username lookups may
- Xtrigger a kernel bug. When a client host connects to your system, and
- Xthe RFC 931 connection from your system to that client is rejected by a
- Xrouter, your kernel may drop all connections with that client. This is
- Xnot a bug in the wrapper programs: complain to your vendor, and don't
- Xenable remote user name lookups until the bug has been fixed.
- X
- XReportedly, SunOS 4.1.1, Next 2.0a, ISC 3.0 with TCP 1.3, and AIX 3.2.2
- Xare OK.
- X
- XSony News/OS 4.51, HP-UX 8-something and Ultrix 4.3 still have the bug.
- XAt the time of writing, a fix for Ultrix is being field tested (CXO-8919).
- X
- XThe following procedure can be used (from outside the tue.nl domain) to
- Xfind out if your kernel has the bug. From the system under test, do:
- X
- X % ftp 131.155.70.100
- X
- XThis command attempts to make an ftp connection to our anonymous ftp
- Xserver (ftp.win.tue.nl). When the connection has been established, run
- Xthe following command from the same system under test, while keeping
- Xthe ftp connection open:
- X
- X % telnet 131.155.70.100 111
- X
- XDo not forget the `111' at the end of the command. This telnet command
- Xattempts to connect to our portmap process. The telnet command should
- Xfail with: "host not reachable", or something like that. If your ftp
- Xconnection gets messed up, you have the bug. If the telnet command does
- Xnot fail, please let me know a.s.a.p.!
- X
- XFor those who care, the bug is that the BSD kernel code was not careful
- Xenough with incoming ICMP UNREACHABLE control messages (it ignored the
- Xlocal and remote port numbers). The bug is still present in the BSD
- XNET/1 source release (1989) but apparently has been fixed in BSD NET/2
- X(1991). You can see it with your own eyes, if you have the courage.
- X
- X7 - Configuration and installation
- X----------------------------------
- X
- X7.1 - Easy configuration and installation
- X-----------------------------------------
- X
- XThe "easy" recipe requires no changes to existing software or
- Xconfiguration files. Basically, you move the daemons that you want to
- Xprotect to a different directory and plug the resulting holes with
- Xcopies of the wrapper programs.
- X
- XIf you don't run Ultrix, you won't need the miscd wrapper program. The
- Xmiscd daemon implements among others the SYSTAT service, which produces
- Xthe same output as the the WHO command.
- X
- XCopy the file Makefile.dist to Makefile, edit the Makefile according to
- Xthe instructions at the beginning of that file, and type `make'.
- X
- XWhen the `make' succeeds the result is two executables (maybe three in
- Xcase of Ultrix). The `try' program can be used to play with host access
- Xcontrol tables and is described in a later section.
- X
- XThe tcpd program can be used to monitor the telnet, finger, ftp, exec,
- Xrsh, rlogin, tftp, talk, comsat and other tcp or udp services that have
- Xa one-to-one mapping onto executable files.
- X
- XThe tcpd program can also be used for services that are marked as
- Xrpc/udp in the inetd configuration file, but not for rpc/tcp services
- Xsuch as rexd. You probably do not want to run rexd anyway. On most
- Xsystems it is even less secure than a wildcard in /etc/hosts.equiv.
- X
- XThe wrappers are not yet able to deal with TLI-based services.
- X
- XDecide which services you want to monitor. Move the corresponding
- Xvendor-provided daemon programs to the location specified by the
- XREAL_DAEMON_DIR constant in the Makefile, and fill the holes with
- Xcopies of the tcpd wrapper. That is, one copy of (or link to) the tcpd
- Xprogram for each service that you want to monitor. For example, to
- Xmonitor the use of your finger service:
- X
- X # mkdir REAL_DAEMON_DIR
- X # mv /usr/etc/in.fingerd REAL_DAEMON_DIR
- X # cp tcpd /usr/etc/in.fingerd
- X
- XThe example applies to SunOS 4. With other UNIX implementations the
- Xnetwork daemons live in /usr/libexec or /usr/sbin, or have no "in."
- Xprefix to their names, but you get the idea.
- X
- XUltrix only: If you want to monitor the SYSTAT service, move the
- Xvendor-provided miscd daemon to the location specified by the
- XREAL_MISCD macro in the Makefile, and install the miscd wrapper into
- Xthe original miscd location.
- X
- XIn the absence of any access-control tables, the daemon wrappers
- Xwill just maintain a record of network connections made to your system.
- X
- X7.2 - Advanced configuration and installation
- X---------------------------------------------
- X
- XThe advanced recipe leaves your daemon executables alone, but involves
- Xsimple modifications to the inetd configuration file.
- X
- XCopy the file Makefile.dist to Makefile. In the Makefile, define the
- XREAL_DAEMON_DIR macro (if you run Ultrix, the REAL_MISCD macro, too) to
- Xreflect the path to your existing network daemons. Don't panic when
- Xsome daemons live elsewhere; we'll deal with that later. Have a look
- Xat the other instructions in the Makefile and type `make'.
- X
- XWhen the `make' succeeds the result is two executables (maybe three in
- Xcase of Ultrix). The `try' program can be used to play with host access
- Xcontrol tables and is described in a later section.
- X
- XThe tcpd program can be used to monitor the telnet, finger, ftp, exec,
- Xrsh, rlogin, tftp, talk, comsat and other tcp or udp services that have
- Xa one-to-one mapping onto executable files.
- X
- XThe tcpd program can also be used for services that are marked as
- Xrpc/udp in the inetd configuration file, but not for rpc/tcp services
- Xsuch as rexd. You probably do not want to run rexd anyway. On most
- Xsystems it is even less secure than a wildcard in /etc/hosts.equiv.
- X
- XThe wrappers are not yet able to deal with TLI-based services.
- X
- XInstall the tcpd command in a suitable place. Apollo UNIX users will
- Xwant to install it under a different name because the name "tcpd" is
- Xalready taken; a suitable name for the wrapper program would be
- X"frontd". Then perform the following edits on the inetd configuration
- Xfile (usually /etc/inetd.conf or /etc/inet/inetd.conf):
- X
- X finger stream tcp nowait nobody /usr/etc/in.fingerd in.fingerd
- X
- Xbecomes:
- X
- X finger stream tcp nowait nobody /usr/etc/tcpd in.fingerd
- X
- XSend a `kill -HUP' to the inetd process to make the change effective.
- X
- XThe example applies to SunOS 4. With other UNIX implementations the
- Xnetwork daemons live in /usr/libexec or /usr/sbin, the network daemons
- Xhave no "in." prefix to their names, or the username field in the inetd
- Xconfiguration file may be missing.
- X
- XWhen the finger service works as expected you can perform similar
- Xchanges for other network services. Do not forget the `kill -HUP'.
- X
- XThe miscd daemon that comes with Ultrix implements several network
- Xservices. It decides what to do by looking at its process name. One of
- Xthe services is systat, which is a kind of limited finger service. If
- Xyou want to monitor the systat service, install the miscd wrapper in
- Xa suitable place and update the inetd configuration file:
- X
- X systat stream tcp nowait /suitable/place/miscd systatd
- X
- XUltrix 4.3 allows you to specify a user id under which the daemon will
- Xbe executed. This feature is not documented in the manual pages. Thus,
- Xthe example would become:
- X
- X systat stream tcp nowait nobody /suitable/place/miscd systatd
- X
- XOlder Ultrix systems still run all their network daemons as root.
- X
- XIn the absence of any access-control tables, the daemon wrappers
- Xwill just maintain a record of network connections made to your system.
- X
- X7.3 - Daemons with arbitrary path names
- X---------------------------------------
- X
- XThe above tcpd examples work fine with network daemons that live in a
- Xcommon directory, but sometimes that is not practical. Having soft
- Xlinks all over your file system is not a clean solution, either.
- X
- XInstead you can specify, in the inetd configuration file, an absolute
- Xpath name for the daemon process name. For example,
- X
- X ntalk dgram udp wait root /usr/etc/tcpd /usr/local/lib/ntalkd
- X
- XWhen the daemon process name is an absolute path name, tcpd ignores the
- Xvalue of the REAL_DAEMON_DIR constant, and uses the last path component
- Xof the daemon process name for logging and for access control.
- X
- X7.4 - Building and testing the access control rules
- X---------------------------------------------------
- X
- XIn order to support access control the wrappers must be compiled with
- Xthe -DHOSTS_ACCESS option. The access control policy is given in the
- Xform of two tables (default: /etc/hosts.allow and /etc/hosts.deny).
- XAccess control is disabled when there are no access control tables, or
- Xwhen the tables are empty.
- X
- XIf you haven't used the wrappers before I recommend that you first run
- Xthem a couple of days without any access control restrictions. The
- Xlogfile records should give you an idea of the process names and of the
- Xhost names that you will have to build into your access control rules.
- X
- XThe syntax of the access control rules is documented in the file
- Xhosts_access.5, which is in `nroff -man' format. This is a lengthy
- Xdocument, and no-one expects you to read it right away from beginning
- Xto end. Instead, after reading the introductory section, skip to the
- Xexamples at the end so that you get a general idea of the language.
- XThen you can appreciate the detailed reference sections near the
- Xbeginning of the document.
- X
- XThe examples in the hosts_access.5 document show two specific types of
- Xaccess control policy: 1) mostly closed (only permitting access from a
- Xlimited number of systems) and 2) mostly open (permitting access from
- Xeveryone except a limited number of trouble makers). You will have to
- Xchoose what model suits your situation best. Implementing a mixed
- Xpolicy should not be overly difficult either.
- X
- XThe `try' command can be used to try out your local access control
- Xfiles. The command syntax is:
- X
- X ./try process_name hostname (e.g.: ./try in.tftpd localhost)
- X
- X ./try process_name address (e.g.: ./try in.tftpd 127.0.0.1)
- X
- XIn order to find out what process name to use, just use the service and
- Xwatch the process name that shows up in the logfile. Alternatively,
- Xyou can look up the name from the inetd configuration file. Coming back
- Xto the tftp example in the tutorial section above:
- X
- X tftp dgram udp wait root /usr/etc/tcpd in.tftpd -s /tftpboot
- X
- XThis entry causes the inetd to run the wrapper program (tcpd) with a
- Xprocess name `in.tftpd'. This is the name that the wrapper will use
- Xwhen scanning the access control tables. Therefore, `in.tftpd' is the
- Xprocess name that should be given to the `try' command. On your system
- Xthe actual inetd.conf entry may differ (tftpd instead of in.tftpd, and
- Xno `root' field), but you get the idea.
- X
- XWhen you specify a host name, the `try' program will use both the host
- Xname and address. This way you can simulate the most common case where
- Xthe wrappers know both the host address and the host name. The `try'
- Xprogram will iterate over all addresses that it can find for the given
- Xhost name.
- X
- XWhen you specify a host address instead of a host name, the `try'
- Xprogram will pretend that the host name is unknown, so that you can
- Xsimulate what happens when the wrapper is unable to look up the remote
- Xhost name.
- X
- XSerious errors in the configuration file syntax will be reported via
- Xthe syslog daemon. Run a `tail -f' on the logfile while playing with
- Xthe `try' command. The tutorial section at the beginning of this file
- Xdescribes where to look for your logfile.
- X
- X7.5 - Other applications
- X------------------------
- X
- XThe access control routines can easily be integrated with other
- Xprograms. The hosts_access.3 manual page (`nroff -man' format)
- Xdescribes the external interface of the libwrap.a library.
- X
- XThe tcpd wrapper can even be used to control access to the smtp port.
- XIn that case, sendmail should not be run as a stand-alone daemon, but
- Xit should be registered in the inetd configuration file. For example:
- X
- X smtp stream tcp nowait root /usr/etc/tcpd /usr/lib/sendmail -bs
- X
- XYou will periodically want to run sendmail to process queued-up
- Xmessages. A crontab entry like:
- X
- X 0,15,30,45 * * * * /usr/lib/sendmail -q
- X
- Xshould take care of that. When you are going to "protect" your sendmail
- Xdaemon this way, you should realize that there are many "unprotected"
- Xsendmail daemons all over the network that can still be abused.
- X
- X8 - Acknowledgements
- X--------------------
- X
- XMany people contributed to the evolution of the programs, by asking
- Xinspiring questions, by suggesting features or bugfixes, or by
- Xsubmitting source code. Nevertheless, all mistakes and bugs in the
- Xwrappers are my own.
- X
- XThanks to Brendan Kehoe (brendan@cs.widener.edu), Heimir Sverrisson
- X(heimir@hafro.is) and Dan Bernstein (brnstnd@kramden.acf.nyu.edu) for
- Xfeedback on an early release of this product. The host name/address
- Xcheck was suggested by John Kimball (jkimball@src.honeywell.com).
- XApollo's UNIX environment has some peculiar quirks: Willem-Jan Withagen
- X(wjw@eb.ele.tue.nl), Pieter Schoenmakers (tiggr@es.ele.tue.nl) and
- XCharles S. Fuller (fuller@wccs.psc.edu) provided assistance. Hal R.
- XBrand (BRAND@addvax.llnl.gov) told me how to get the remote IP address
- Xin case of datagram-oriented services, and suggested the optional shell
- Xcommand feature. Shabbir Safdar (shabby@mentor.cc.purdue.edu) provided
- Xa first version of a much-needed manual page. Granville Boman Goza, IV
- X(gbg@sei.cmu.edu) suggested to use the remote IP address even when the
- Xhost name is available. Casper H.S. Dik (casper@fwi.uva.nl) provided
- Xadditional insight into DNS spoofing techniques. The bogus daemon
- Xfeature was inspired by code from Andrew Macpherson (BNR Europe Ltd).
- XSteve Bellovin (smb@research.att.com) confirmed some of my suspicions
- Xabout the darker sides of TCP/IP insecurity.
- X
- XIn no particular order, Howard Chu (hyc@hanauma.jpl.nasa.gov), John P.
- XRouillard (rouilj@cs.umb.edu), Darren Reed (avalon@coombs.anu.edu.au),
- XIcarus Sparry (I.Sparry@gdr.bath.ac.uk), Scott Schwartz (schwartz@
- Xcs.psu.edu), John A. Kunze (jak@violet.berkeley.edu), Daniel Len
- XSchales (dan@engr.latech.edu), Chris Turbeville <turbo@cse.uta.edu>,
- XPaul Kranenburg <pk@cs.few.eur.nl>, and many, many others provided
- Xfixes, code fragments, or other improvements to the wrappers.
- X
- X Wietse Venema (wietse@wzv.win.tue.nl)
- X Department of Mathematics and Computing Science
- X Eindhoven University of Technology
- X P.O. Box 513
- X 5600 MB Eindhoven
- X The Netherlands
- END_OF_README
- if test 34888 -ne `wc -c <README`; then
- echo shar: \"README\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f miscd.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"miscd.c\"
- else
- echo shar: Extracting \"miscd.c\" \(2602 characters\)
- sed "s/^X//" >miscd.c <<'END_OF_miscd.c'
- X /*
- X * Front end to the ULTRIX miscd service. The front end logs the remote host
- X * name and then invokes the real miscd daemon. Install as "/usr/etc/miscd",
- X * after moving the real miscd daemon to the "/usr/etc/..." directory.
- X * Connections and diagnostics are logged through syslog(3).
- X *
- X * The Ultrix miscd program implements (among others) the systat service, which
- X * pipes the output from who(1) to stdout. This information is potentially
- X * useful to systems crackers.
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) miscd.c 1.4 93/03/07 22:47:28";
- X#endif
- X
- X/* System libraries. */
- X
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#include <syslog.h>
- X
- X/* Local stuff. */
- X
- X#include "patchlevel.h"
- X#include "log_tcp.h"
- X
- X/* The following specifies where the vendor-provided daemon should go. */
- X
- X#ifndef REAL_MISCD
- X#define REAL_MISCD "/usr/etc/.../miscd"
- X#endif
- X
- Xint log_severity = SEVERITY; /* run-time adjustable */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X struct from_host from;
- X int from_stat;
- X
- X /* Attempt to prevent the creation of world-writable files. */
- X
- X#ifdef DAEMON_UMASK
- X umask(DAEMON_UMASK);
- X#endif
- X
- X /*
- X * Open a channel to the syslog daemon. Older versions of openlog()
- X * require only two arguments.
- X */
- X
- X#ifdef LOG_MAIL
- X (void) openlog(argv[0], LOG_PID, FACILITY);
- X#else
- X (void) openlog(argv[0], LOG_PID);
- X#endif
- X
- X /*
- X * Find out and verify the remote host name. Sites concerned with
- X * security may choose to refuse connections from hosts that pretend to
- X * have someone elses host name.
- X */
- X
- X from_stat = fromhost(&from);
- X#ifdef PARANOID
- X if (from_stat == -1)
- X refuse(&from);
- X#endif
- X
- X /*
- X * The BSD rlogin and rsh daemons that came out after 4.3 BSD disallow
- X * socket options at the IP level. They do so for a good reason. Let's
- X * follow their example.
- X */
- X
- X#ifdef KILL_IP_OPTIONS
- X fix_options(&from);
- X#endif
- X
- X /*
- X * Check whether this host can access the service in argv[0]. The
- X * access-control code invokes optional shell commands as specified in
- X * the access-control tables.
- X */
- X
- X#ifdef HOSTS_ACCESS
- X if (!hosts_access(argv[0], &from))
- X refuse(&from);
- X#endif
- X
- X /* Report remote client and invoke the real daemon program. */
- X
- X syslog(log_severity, "connect from %s", hosts_info(&from));
- X (void) execv(REAL_MISCD, argv);
- X syslog(LOG_ERR, "%s: %m", REAL_MISCD);
- X clean_exit(&from);
- X /* NOTREACHED */
- X}
- END_OF_miscd.c
- if test 2602 -ne `wc -c <miscd.c`; then
- echo shar: \"miscd.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f tcpd.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"tcpd.c\"
- else
- echo shar: Extracting \"tcpd.c\" \(2995 characters\)
- sed "s/^X//" >tcpd.c <<'END_OF_tcpd.c'
- X /*
- X * General front end for stream and datagram IP services. This program logs
- X * the remote host name and then invokes the real daemon. For example,
- X * install as /usr/etc/{tftpd,fingerd,telnetd,ftpd,rlogind,rshd,rexecd},
- X * after saving the real daemons in the directory "/usr/etc/...". This
- X * arrangement requires that the network daemons are started by inetd or
- X * something similar. Connections and diagnostics are logged through
- X * syslog(3).
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) tcpd.c 1.4 93/03/07 22:47:32";
- X#endif
- X
- X/* System libraries. */
- X
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X#include <syslog.h>
- X
- Xextern char *strrchr();
- Xextern char *strcpy();
- X
- X#ifndef MAXPATHNAMELEN
- X#define MAXPATHNAMELEN BUFSIZ
- X#endif
- X
- X/* Local stuff. */
- X
- X#include "patchlevel.h"
- X#include "log_tcp.h"
- X
- X/* The following specifies where the vendor-provided daemons should go. */
- X
- X#ifndef REAL_DAEMON_DIR
- X#define REAL_DAEMON_DIR "/usr/etc/..."
- X#endif
- X
- Xint log_severity = SEVERITY; /* run-time adjustable */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X struct from_host from;
- X int from_stat;
- X char path[MAXPATHNAMELEN];
- X
- X /* Attempt to prevent the creation of world-writable files. */
- X
- X#ifdef DAEMON_UMASK
- X umask(DAEMON_UMASK);
- X#endif
- X
- X /*
- X * If argv[0] is an absolute path name, ignore REAL_DAEMON_DIR, and strip
- X * argv[0] to its basename.
- X */
- X
- X if (argv[0][0] == '/') {
- X strcpy(path, argv[0]);
- X argv[0] = strrchr(argv[0], '/') + 1;
- X } else {
- X sprintf(path, "%s/%s", REAL_DAEMON_DIR, argv[0]);
- X }
- X
- X /*
- X * Open a channel to the syslog daemon. Older versions of openlog()
- X * require only two arguments.
- X */
- X
- X#ifdef LOG_MAIL
- X (void) openlog(argv[0], LOG_PID, FACILITY);
- X#else
- X (void) openlog(argv[0], LOG_PID);
- X#endif
- X
- X /*
- X * Find out and verify the remote host name. Sites concerned with
- X * security may choose to refuse connections from hosts that pretend to
- X * have someone elses host name.
- X */
- X
- X from_stat = fromhost(&from);
- X#ifdef PARANOID
- X if (from_stat == -1)
- X refuse(&from);
- X#endif
- X
- X /*
- X * The BSD rlogin and rsh daemons that came out after 4.3 BSD disallow
- X * socket options at the IP level. They do so for a good reason. Let's
- X * follow their example.
- X */
- X
- X#ifdef KILL_IP_OPTIONS
- X fix_options(&from);
- X#endif
- X
- X /*
- X * Check whether this host can access the service in argv[0]. The
- X * access-control code invokes optional shell commands as specified in
- X * the access-control tables.
- X */
- X
- X#ifdef HOSTS_ACCESS
- X if (!hosts_access(argv[0], &from))
- X refuse(&from);
- X#endif
- X
- X /* Report remote client and invoke the real daemon program. */
- X
- X syslog(log_severity, "connect from %s", hosts_info(&from));
- X (void) execv(path, argv);
- X syslog(LOG_ERR, "%s: %m", path);
- X clean_exit(&from);
- X /* NOTREACHED */
- X}
- END_OF_tcpd.c
- if test 2995 -ne `wc -c <tcpd.c`; then
- echo shar: \"tcpd.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f fromhost.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"fromhost.c\"
- else
- echo shar: Extracting \"fromhost.c\" \(8144 characters\)
- sed "s/^X//" >fromhost.c <<'END_OF_fromhost.c'
- X /*
- X * fromhost() determines the type of connection (datagram, stream), the name
- X * and address of the host at the other end of standard input, and the
- X * remote user name (if RFC 931 lookups are enabled). A host name of "stdin"
- X * is returned if the program is run from a tty. The value "unknown" is
- X * returned as a placeholder for information that could not be looked up.
- X * All results are in static memory.
- X *
- X * The return status is (-1) if the remote host pretends to have someone elses
- X * host name, otherwise a zero status is returned.
- X *
- X * Diagnostics are reported through syslog(3).
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) fromhost.c 1.7 93/03/07 22:47:34";
- X#endif
- X
- X/* System libraries. */
- X
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <stdio.h>
- X#include <syslog.h>
- X#include <errno.h>
- X
- Xextern char *inet_ntoa();
- Xextern char *strncpy();
- Xextern char *strcpy();
- X
- X/* In case not defined in <sys/param.h>. */
- X
- X#ifndef MAXHOSTNAMELEN
- X#define MAXHOSTNAMELEN 1024 /* string with host name */
- X#endif
- X
- X/* Local stuff. */
- X
- X#include "log_tcp.h"
- X
- X/* Forward declarations. */
- X
- Xstatic int matchname();
- X
- X/* The following are to be used in assignment context, not in comparisons. */
- X
- X#define GOOD 1
- X#define BAD 0
- X
- X/* Initially, we know nothing about the origin of the connection. */
- X
- Xstatic struct from_host from_unknown = {
- X 0, /* connected/unconnected */
- X FROM_UNKNOWN, /* remote host name */
- X FROM_UNKNOWN, /* remote host address */
- X "", /* remote user name */
- X};
- X
- X /*
- X * With early SunOS 5 versions, recvfrom() does not completely fill in the
- X * source address structure when doing a non-destructive read. The following
- X * code works around the problem. It does no harm on "normal" systems.
- X */
- X
- X#ifdef RECVFROM_BUG
- X
- Xstatic int fix_recvfrom(sock, buf, buflen, flags, from, fromlen)
- Xint sock;
- Xchar *buf;
- Xint buflen;
- Xint flags;
- Xstruct sockaddr *from;
- Xint *fromlen;
- X{
- X int ret;
- X
- X /* Assume that both ends of a socket belong to the same address family. */
- X
- X if ((ret = recvfrom(sock, buf, buflen, flags, from, fromlen)) >= 0) {
- X if (from->sa_family == 0) {
- X struct sockaddr my_addr;
- X int my_addr_len = sizeof(my_addr);
- X
- X if (getsockname(0, &my_addr, &my_addr_len)) {
- X syslog(LOG_ERR, "getsockname: %m");
- X } else {
- X from->sa_family = my_addr.sa_family;
- X }
- X }
- X }
- X return (ret);
- X}
- X
- X#define recvfrom fix_recvfrom
- X#endif
- X
- X /*
- X * The Apollo SR10.3 and some SYSV4 getpeername(2) versions do not return an
- X * error in case of a datagram-oriented socket. Instead, they claim that all
- X * UDP requests come from address 0.0.0.0. The following code works around
- X * the problem. It does no harm on "normal" systems.
- X */
- X
- X#ifdef GETPEERNAME_BUG
- X
- Xstatic int fix_getpeername(sock, sa, len)
- Xint sock;
- Xstruct sockaddr *sa;
- Xint *len;
- X{
- X int ret;
- X struct sockaddr_in *sin = (struct sockaddr_in *) sa;
- X
- X if ((ret = getpeername(sock, sa, len)) >= 0
- X && sa->sa_family == AF_INET
- X && sin->sin_addr.s_addr == 0) {
- X errno = ENOTCONN;
- X return (-1);
- X } else {
- X return (ret);
- X }
- X}
- X
- X#define getpeername fix_getpeername
- X#endif
- X
- X/* fromhost - find out what is at the other end of standard input */
- X
- Xint fromhost(f)
- Xstruct from_host *f;
- X{
- X static struct sockaddr sa;
- X struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
- X struct hostent *hp;
- X int length = sizeof(sa);
- X char buf[BUFSIZ];
- X static char addr_buf[FROM_ADDRLEN];
- X static char name_buf[MAXHOSTNAMELEN];
- X
- X /*
- X * There are so many results and so many early returns that it seems
- X * safest to first initialize all results to UNKNOWN.
- X */
- X
- X *f = from_unknown;
- X
- X /*
- X * Look up the remote host address. Hal R. Brand <BRAND@addvax.llnl.gov>
- X * suggested how to get the remote host info in case of UDP connections:
- X * peek at the first message without actually looking at its contents.
- X */
- X
- X if (getpeername(0, &sa, &length) >= 0) { /* assume TCP request */
- X f->sock_type = FROM_CONNECTED;
- X } else {
- X switch (errno) {
- X default:
- X if (isatty(0)) /* stdin is not a socket */
- X f->name = "stdin";
- X else
- X syslog(LOG_ERR, "getpeername: %m"); /* other, punt */
- X return (0);
- X case ENOTCONN: /* assume UDP request */
- X length = sizeof(sa);
- X if (recvfrom(0, buf, sizeof(buf), MSG_PEEK, &sa, &length) < 0) {
- X syslog(LOG_ERR, "recvfrom: %m");
- X return (0);
- X }
- X#ifdef really_paranoid
- X memset(buf, 0 sizeof(buf));
- X#endif
- X f->sock_type = FROM_UNCONNECTED;
- X break;
- X }
- X }
- X
- X /*
- X * At present, we can only deal with the AF_INET address family. Some
- X * implementations of System V religion never fill in the address family
- X * field in case of UDP connections. If that happens, you may want to
- X * take the chance and assume that we're dealing with TCP/IP anyway.
- X */
- X
- X#ifdef ADDRESS_FAMILY_BUG
- X if (sa.sa_family == 0)
- X sa.sa_family = AF_INET;
- X#endif
- X if (sa.sa_family != AF_INET) {
- X syslog(LOG_ERR, "unexpected address family %ld", (long) sa.sa_family);
- X return (0);
- X }
- X /* Save the host address. A later inet_ntoa() call may clobber it. */
- X
- X f->sin = sin;
- X f->addr = strcpy(addr_buf, inet_ntoa(sin->sin_addr));
- X
- X /* Look up the remote user name. Does not work for UDP services. */
- X
- X#if defined(RFC931) && !defined(USER_AT_HOST) && !defined(RFC931_OPTION)
- X if (f->sock_type == FROM_CONNECTED)
- X f->user = rfc931_name(sin);
- X#endif
- X
- X /* Look up the remote host name. */
- X
- X if ((hp = gethostbyaddr((char *) &sin->sin_addr,
- X sizeof(sin->sin_addr),
- X AF_INET)) == 0) {
- X return (0);
- X }
- X /* Save the host name. A later gethostbyxxx() call may clobber it. */
- X
- X f->name = strncpy(name_buf, hp->h_name, sizeof(name_buf) - 1);
- X name_buf[sizeof(name_buf) - 1] = 0;
- X
- X /*
- X * Verify that the host name does not belong to someone else. If host
- X * name verification fails, pretend that the host name lookup failed.
- X */
- X
- X if (matchname(f->name, sin->sin_addr)) {
- X return (0);
- X } else {
- X f->name = FROM_UNKNOWN;
- X return (-1); /* verification failed */
- X }
- X}
- X
- X/* matchname - determine if host name matches IP address */
- X
- Xstatic int matchname(remotehost, addr)
- Xchar *remotehost;
- Xstruct in_addr addr;
- X{
- X struct hostent *hp;
- X int i;
- X
- X if ((hp = gethostbyname(remotehost)) == 0) {
- X
- X /*
- X * Unable to verify that the host name matches the address. This may
- X * be a transient problem or a botched name server setup. We decide
- X * to play safe.
- X */
- X
- X syslog(LOG_ERR, "gethostbyname(%s): lookup failure", remotehost);
- X return (BAD);
- X
- X } else {
- X
- X /*
- X * Make sure that gethostbyname() returns the "correct" host name.
- X * Unfortunately, gethostbyname("localhost") sometimes yields
- X * "localhost.domain". Since the latter host name comes from the
- X * local DNS, we just have to trust it (all bets are off if the local
- X * DNS is perverted). We always check the address list, though.
- X */
- X
- X if (strcasecmp(remotehost, hp->h_name)
- X && strcasecmp(remotehost, "localhost")) {
- X syslog(LOG_ERR, "host name/name mismatch: %s != %s",
- X remotehost, hp->h_name);
- X return (BAD);
- X }
- X /* Look up the host address in the address list we just got. */
- X
- X for (i = 0; hp->h_addr_list[i]; i++) {
- X if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
- X return (GOOD);
- X }
- X
- X /*
- X * The host name does not map to the original host address. Perhaps
- X * someone has compromised a name server. More likely someone botched
- X * it, but that could be dangerous, too.
- X */
- X
- X syslog(LOG_ERR, "host name/address mismatch: %s != %s",
- X inet_ntoa(addr), hp->h_name);
- X return (BAD);
- X }
- X}
- X
- X#ifdef TEST
- X
- X/* Code for stand-alone testing. */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X struct from_host from;
- X
- X#ifdef LOG_MAIL
- X (void) openlog(argv[0], LOG_PID, FACILITY);
- X#else
- X (void) openlog(argv[0], LOG_PID);
- X#endif
- X (void) fromhost(&from);
- X printf("%s\n", hosts_info(&from));
- X return (0);
- X}
- X
- X#endif
- END_OF_fromhost.c
- if test 8144 -ne `wc -c <fromhost.c`; then
- echo shar: \"fromhost.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f hosts_access.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"hosts_access.c\"
- else
- echo shar: Extracting \"hosts_access.c\" \(11173 characters\)
- sed "s/^X//" >hosts_access.c <<'END_OF_hosts_access.c'
- X /*
- X * This module implements a simple access control language that is based on
- X * host (or domain) names, netgroup, internet addresses (or network numbers)
- X * and daemon process names. When a match is found an optional shell command
- X * is executed and the search is terminated.
- X *
- X * Diagnostics are reported through syslog(3).
- X *
- X * Compile with -DNETGROUP if your library provides support for netgroups.
- X *
- X * Compile with -DUSER_AT_HOST for rule-driven username lookups.
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) hosts_access.c 1.10 93/03/07 22:47:36";
- X#endif
- X
- X /* System libraries. */
- X
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <stdio.h>
- X#include <syslog.h>
- X#include <ctype.h>
- X#include <errno.h>
- X
- Xextern char *fgets();
- Xextern char *strchr();
- Xextern char *strtok();
- X
- X#ifndef INADDR_NONE
- X#define INADDR_NONE (-1) /* XXX should be 0xffffffff */
- X#endif
- X
- X/* Local stuff. */
- X
- X#include "log_tcp.h"
- X
- X#ifdef INET_ADDR_BUG
- X#include "inet_addr_fix"
- X#endif
- X
- X/* Delimiters for lists of daemons or clients. */
- X
- Xstatic char sep[] = ", \t";
- X
- X/* Constants to be used in assignments only, not in comparisons... */
- X
- X#define YES 1
- X#define NO 0
- X#define FAIL (-1)
- X
- X/* Forward declarations. */
- X
- Xstatic int table_match();
- Xstatic int list_match();
- Xstatic int client_match();
- Xstatic int string_match();
- Xstatic int masked_match();
- Xstatic char *xgets();
- X
- X/* The user@host access control. Trivial to add but complicates use. */
- X
- X#ifdef USER_AT_HOST
- Xstatic int userhost_match();
- X#define CLIENT_MATCH userhost_match
- X#else
- X#define CLIENT_MATCH client_match
- X#endif
- X
- X/* Size of logical line buffer. */
- X
- X#define BUFLEN 2048
- X
- X/* hosts_access - host access control facility */
- X
- Xint hosts_access(daemon, client)
- Xchar *daemon;
- Xstruct from_host *client; /* host or user name may be empty */
- X{
- X
- X /*
- X * If the (daemon, client) pair is matched by an entry in the file
- X * /etc/hosts.allow, access is granted. Otherwise, if the (daemon,
- X * client) pair is matched by an entry in the file /etc/hosts.deny,
- X * access is denied. Otherwise, access is granted. A non-existent
- X * access-control file is treated as an empty file.
- X */
- X
- X if (table_match(HOSTS_ALLOW, daemon, client))
- X return (YES);
- X if (table_match(HOSTS_DENY, daemon, client))
- X return (NO);
- X return (YES);
- X}
- X
- X/* table_match - match table entries with (daemon, client) pair */
- X
- Xstatic int table_match(table, daemon, client)
- Xchar *table;
- Xchar *daemon;
- Xstruct from_host *client; /* host or user name may be empty */
- X{
- X FILE *fp;
- X char sv_list[BUFLEN]; /* becomes list of daemons */
- X char *cl_list; /* becomes list of clients */
- X char *sh_cmd; /* becomes optional shell command */
- X int match;
- X int end;
- X
- X /* The following variables should always be tested together. */
- X
- X int sv_match = NO; /* daemon matched */
- X int cl_match = NO; /* client matced */
- X
- X /*
- X * Process the table one logical line at a time. Lines that begin with a
- X * '#' character are ignored. Non-comment lines are broken at the ':'
- X * character (we complain if there is none). The first field is matched
- X * against the daemon process name (argv[0]), the second field against
- X * the host name or address. A non-existing table is treated as if it
- X * were an empty table. The search terminates at the first matching rule.
- X * When a match is found an optional shell command is executed.
- X */
- X
- X if (fp = fopen(table, "r")) {
- X while (!(sv_match && cl_match) && xgets(sv_list, sizeof(sv_list), fp)) {
- X if (sv_list[end = strlen(sv_list) - 1] != '\n') {
- X syslog(LOG_ERR, "%s: missing newline or line too long", table);
- X continue;
- X }
- X if (sv_list[0] == '#') /* skip comments */
- X continue;
- X while (end > 0 && isspace(sv_list[end - 1]))
- X end--;
- X sv_list[end] = '\0'; /* strip trailing whitespace */
- X if (sv_list[0] == 0) /* skip blank lines */
- X continue;
- X if ((cl_list = strchr(sv_list, ':')) == 0) {
- X syslog(LOG_ERR, "%s: malformed entry: \"%s\"", table, sv_list);
- X continue;
- X }
- X *cl_list++ = '\0'; /* split 1st and 2nd fields */
- X if ((sh_cmd = strchr(cl_list, ':')) != 0)
- X *sh_cmd++ = '\0'; /* split 2nd and 3rd fields */
- X if ((sv_match = list_match(sv_list, daemon, string_match)))
- X cl_match = list_match(cl_list, (char *) client, CLIENT_MATCH);
- X }
- X (void) fclose(fp);
- X } else if (errno != ENOENT) {
- X syslog(LOG_ERR, "cannot open %s: %m", table);
- X }
- X match = (sv_match == YES && cl_match == YES);
- X if (match && sh_cmd)
- X OPTIONS_STYLE(sh_cmd, daemon, client);
- X return (match);
- X}
- X
- X/* list_match - match an item against a list of tokens with exceptions */
- X
- Xstatic int list_match(list, item, match_fn)
- Xchar *list;
- Xchar *item;
- Xint (*match_fn) ();
- X{
- X char *tok;
- X int match = NO;
- X
- X /*
- X * Process tokens one at a time. We have exhausted all possible matches
- X * when we reach an "EXCEPT" token or the end of the list. If we do find
- X * a match, look for an "EXCEPT" list and recurse to determine whether
- X * the match is affected by any exceptions.
- X */
- X
- X for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) {
- X if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
- X break;
- X if (match = (*match_fn) (tok, item)) /* YES or FAIL */
- X break;
- X }
- X /* Process exceptions to YES or FAIL matches. */
- X
- X if (match != NO) {
- X while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT"))
- X /* VOID */ ;
- X if (tok == 0 || list_match((char *) 0, item, match_fn) == NO)
- X return (match);
- X }
- X return (NO);
- X}
- X
- X/* client_match - match host name and address against token */
- X
- Xstatic int client_match(tok, item)
- Xchar *tok;
- Xchar *item;
- X{
- X struct from_host *client = (struct from_host *) item;
- X int match;
- X
- X /*
- X * Try to match the address first. If that fails, try to match the host
- X * name if available.
- X */
- X
- X if ((match = string_match(tok, client->addr)) == 0)
- X if (client->name[0] != 0)
- X match = string_match(tok, client->name);
- X return (match);
- X}
- X
- X#ifdef USER_AT_HOST
- X
- X/* userhost_match - do user@host access control */
- X
- Xstatic int userhost_match(tok, item)
- Xchar *tok;
- Xchar *item;
- X{
- X struct from_host *client = (struct from_host *) item;
- X int match = NO;
- X char *at;
- X int host_match;
- X int user_match;
- X
- X /*
- X * Warning: experimental code, enabled only when USER_AT_HOST is defined.
- X *
- X * Basically, you specify user_pattern@host_pattern where remote username
- X * lookups are desired, and plain host_pattern for all other cases. The
- X * syntax of user name patterns is the same as for hosts or daemons, but
- X * ALL is probably the only user_pattern that makes sense.
- X *
- X * In case of UDP connections, the result of username lookup will always be
- X * "unknown".
- X *
- X * Return FAIL if we match a pattern of the form user@FAIL or FAIL@host:
- X * FAIL, like NO, is transitive. According to some people, such patterns
- X * should be taken out and shot. Good news: FAIL is on its way out.
- X */
- X
- X if (at = strchr(tok + 1, '@')) { /* user@host */
- X *at = 0;
- X if (host_match = client_match(at + 1, item)) {
- X if (client->user[0] == 0) {
- X if (client->sock_type != FROM_CONNECTED) {
- X client->user = FROM_UNKNOWN;
- X } else if (client->sin == 0) {
- X syslog(LOG_ERR, "no socket info for user name lookup");
- X client->user = FROM_UNKNOWN;
- X } else {
- X client->user = rfc931_name(client->sin);
- X }
- X }
- X user_match = string_match(tok, client->user);
- X if (user_match == NO || user_match == FAIL) {
- X match = user_match;
- X } else {
- X match = host_match;
- X }
- X }
- X *at = '@';
- X } else { /* host */
- X match = client_match(tok, item);
- X }
- X return (match);
- X}
- X
- X#endif /* USER_AT_HOST */
- X
- X/* string_match - match string against token */
- X
- Xstatic int string_match(tok, string)
- Xchar *tok;
- Xchar *string;
- X{
- X int tok_len;
- X int str_len;
- X char *cut;
- X#ifdef NETGROUP
- X static char *mydomain = 0;
- X#endif
- X
- X /*
- X * Return YES if a token has the magic value "ALL". Return FAIL if the
- X * token is "FAIL". If the token starts with a "." (domain name), return
- X * YES if it matches the last fields of the string. If the token has the
- X * magic value "LOCAL", return YES if the string does not contain a "."
- X * character. If the token ends on a "." (network number), return YES if
- X * it matches the first fields of the string. If the token begins with a
- X * "@" (netgroup name), return YES if the string is a (host) member of
- X * the netgroup. Return YES if the token fully matches the string. If the
- X * token is a netnumber/netmask pair, return YES if the address is a
- X * member of the specified subnet.
- X */
- X
- X if (tok[0] == '.') { /* domain: match last fields */
- X if ((str_len = strlen(string)) > (tok_len = strlen(tok))
- X && strcasecmp(tok, string + str_len - tok_len) == 0)
- X return (YES);
- X } else if (tok[0] == '@') { /* netgroup: look it up */
- X#ifdef NETGROUP
- X if (mydomain == 0)
- X yp_get_default_domain(&mydomain);
- X if (!isdigit(string[0])
- X && innetgr(tok + 1, string, (char *) 0, mydomain))
- X return (YES);
- X#else
- X syslog(LOG_ERR, "wrapper: netgroup support is not configured");
- X return (NO);
- X#endif
- X } else if (strcasecmp(tok, "ALL") == 0) { /* all: match any */
- X return (YES);
- X } else if (strcasecmp(tok, "FAIL") == 0) { /* fail: match any */
- X return (FAIL);
- X } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */
- X if (strchr(string, '.') == 0 && strcasecmp(string, "unknown") != 0)
- X return (YES);
- X } else if (!strcasecmp(tok, string)) { /* match host name or address */
- X return (YES);
- X } else if (tok[(tok_len = strlen(tok)) - 1] == '.') { /* network */
- X if (strncmp(tok, string, tok_len) == 0)
- X return (YES);
- X } else if ((cut = strchr(tok, '/')) != 0) { /* netnumber/netmask */
- X if (isdigit(string[0]) && masked_match(tok, cut, string))
- X return (YES);
- X }
- X return (NO);
- X}
- X
- X/* masked_match - match address against netnumber/netmask */
- X
- Xstatic int masked_match(tok, slash, string)
- Xchar *tok;
- Xchar *slash;
- Xchar *string;
- X{
- X unsigned long net;
- X unsigned long mask;
- X unsigned long addr;
- X
- X if ((addr = inet_addr(string)) == INADDR_NONE)
- X return (NO);
- X *slash = 0;
- X net = inet_addr(tok);
- X *slash = '/';
- X if (net == INADDR_NONE || (mask = inet_addr(slash + 1)) == INADDR_NONE) {
- X syslog(LOG_ERR, "bad net/mask access control: %s", tok);
- X return (NO);
- X }
- X return ((addr & mask) == net);
- X}
- X
- X/* xgets - fgets() with backslash-newline stripping */
- X
- Xstatic char *xgets(buf, len, fp)
- Xchar *buf;
- Xint len;
- XFILE *fp;
- X{
- X int got;
- X char *start = buf;
- X
- X for (;;) {
- X if (fgets(buf, len, fp) == 0)
- X return (buf > start ? start : 0);
- X got = strlen(buf);
- X if (got >= 2 && buf[got - 2] == '\\' && buf[got - 1] == '\n') {
- X got -= 2;
- X buf += got;
- X len -= got;
- X buf[0] = 0;
- X } else {
- X return (start);
- X }
- X }
- X}
- END_OF_hosts_access.c
- if test 11173 -ne `wc -c <hosts_access.c`; then
- echo shar: \"hosts_access.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f shell_cmd.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"shell_cmd.c\"
- else
- echo shar: Extracting \"shell_cmd.c\" \(2883 characters\)
- sed "s/^X//" >shell_cmd.c <<'END_OF_shell_cmd.c'
- X /*
- X * shell_cmd() takes a shell command template and performs %a (host
- X * address), %c (client info), %h (host name or address), %d (daemon name),
- X * %p (process id) and %u (user name) substitutions. The result is executed
- X * by a /bin/sh child process, with standard input, standard output and
- X * standard error connected to /dev/null.
- X *
- X * Diagnostics are reported through syslog(3).
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) shell_cmd.c 1.3 93/03/07 22:47:39";
- X#endif
- X
- X/* System libraries. */
- X
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#include <signal.h>
- X#include <stdio.h>
- X#include <syslog.h>
- X
- Xextern char *strncpy();
- Xextern void closelog();
- Xextern void exit();
- X
- X/* Local stuff. */
- X
- X#include "log_tcp.h"
- X
- X/* Forward declarations. */
- X
- Xstatic void do_child();
- X
- X/* shell_cmd - expand %<char> sequences and execute shell command */
- X
- Xvoid shell_cmd(string, daemon, client)
- Xchar *string;
- Xchar *daemon;
- Xstruct from_host *client;
- X{
- X char cmd[BUFSIZ];
- X int child_pid;
- X int wait_pid;
- X int daemon_pid = getpid();
- X
- X /*
- X * Most of the work is done within the child process, to minimize the
- X * risk of damage to the parent.
- X */
- X
- X switch (child_pid = fork()) {
- X case -1: /* error */
- X syslog(LOG_ERR, "fork: %m");
- X break;
- X case 00: /* child */
- X percent_x(cmd, sizeof(cmd), string, daemon, client, daemon_pid);
- X do_child(daemon, cmd);
- X /* NOTREACHED */
- X default: /* parent */
- X while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid)
- X /* void */ ;
- X }
- X}
- X
- X/* do_child - exec command with { stdin, stdout, stderr } to /dev/null */
- X
- Xstatic void do_child(myname, command)
- Xchar *myname;
- Xchar *command;
- X{
- X char *error = 0;
- X int tmp_fd;
- X
- X /*
- X * SunOS 4.x may send a SIGHUP to grandchildren if the child exits first.
- X * Sessions and process groups make old and grown-up programmers tear out
- X * what little hair is left and run away crying.
- X */
- X
- X signal(SIGHUP, SIG_IGN);
- X
- X /*
- X * Close a bunch of file descriptors. The Ultrix inetd only passes stdin,
- X * but other inetd implementations set up stdout as well. Ignore errors.
- X */
- X
- X closelog();
- X for (tmp_fd = 0; tmp_fd < 10; tmp_fd++)
- X (void) close(tmp_fd);
- X
- X /* Set up new stdin, stdout, stderr, and exec the shell command. */
- X
- X if (open("/dev/null", 2) != 0) {
- X error = "open /dev/null: %m";
- X } else if (dup(0) != 1 || dup(0) != 2) {
- X error = "dup: %m";
- X } else {
- X (void) execl("/bin/sh", "sh", "-c", command, (char *) 0);
- X error = "execl /bin/sh: %m";
- X }
- X
- X /* We can reach the following code only if there was an error. */
- X
- X#ifdef LOG_MAIL
- X (void) openlog(myname, LOG_PID, FACILITY);
- X#else
- X (void) openlog(myname, LOG_PID);
- X#endif
- X syslog(LOG_ERR, error);
- X exit(0);
- X}
- END_OF_shell_cmd.c
- if test 2883 -ne `wc -c <shell_cmd.c`; then
- echo shar: \"shell_cmd.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f log_tcp.h -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"log_tcp.h\"
- else
- echo shar: Extracting \"log_tcp.h\" \(1448 characters\)
- sed "s/^X//" >log_tcp.h <<'END_OF_log_tcp.h'
- X/* @(#) log_tcp.h 1.3 93/03/07 22:47:41 */
- X
- X/* Location of the access control files. */
- X
- X#ifndef HOSTS_ALLOW
- X#define HOSTS_ALLOW "/etc/hosts.allow"
- X#endif
- X
- X#ifndef HOSTS_DENY
- X#define HOSTS_DENY "/etc/hosts.deny"
- X#endif
- X
- X /* Structure filled in by the fromhost() routine. */
- X
- Xstruct from_host {
- X int sock_type; /* socket type, see below */
- X char *name; /* host name */
- X char *addr; /* host address */
- X char *user; /* user name */
- X struct sockaddr_in *sin; /* their side of the link */
- X};
- X
- X#define FROM_UNKNOWN "unknown" /* name or address lookup failed */
- X#define FROM_HOST(f) \
- X (((f)->name[0] && strcmp((f)->name, FROM_UNKNOWN)) ? (f)->name : (f)->addr)
- X
- X#define FROM_ADDRLEN (4*3+3+1) /* string with IP address */
- X
- X/* Socket types: 0 means unknown. */
- X
- X#define FROM_CONNECTED 1 /* connection-oriented */
- X#define FROM_UNCONNECTED 2 /* non connection-oriented */
- X
- X/* Global functions. */
- X
- Xextern int fromhost(); /* get/validate remote host info */
- Xextern int hosts_access(); /* access control */
- Xextern void refuse(); /* refuse request */
- Xextern void shell_cmd(); /* execute shell command */
- Xextern void percent_x(); /* do %<char> expansion */
- Xextern char *rfc931_name(); /* remote name from RFC 931 daemon */
- Xextern char *hosts_info(); /* show origin of connection */
- Xextern void clean_exit(); /* clean up and exit */
- X
- X/* Global variables. */
- X
- Xextern int log_severity; /* for connection logging */
- END_OF_log_tcp.h
- if test 1448 -ne `wc -c <log_tcp.h`; then
- echo shar: \"log_tcp.h\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f try.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"try.c\"
- else
- echo shar: Extracting \"try.c\" \(3200 characters\)
- sed "s/^X//" >try.c <<'END_OF_try.c'
- X /*
- X * try - program to try out host access-control tables, including the
- X * optional shell commands.
- X *
- X * usage: try process_name host_name_or_address
- X *
- X * where process_name is a daemon process name (argv[0] value). If a host name
- X * is specified, both the name and address will be used to check the address
- X * control tables. If a host address is specified, the program pretends that
- X * host name lookup failed.
- X *
- X * Most errors will be reported to the syslog daemon, so you'd better keep a
- X * tail on the logfile.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) try.c 1.3 93/03/07 22:47:43";
- X#endif
- X
- X#include <sys/types.h>
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <netdb.h>
- X#include <stdio.h>
- X#include <syslog.h>
- X
- X#ifdef HOSTS_ACCESS
- X
- X#ifndef INADDR_NONE
- X#define INADDR_NONE (-1) /* XXX should be 0xffffffff */
- X#endif
- X
- X#include "log_tcp.h"
- X
- X#ifdef INET_ADDR_BUG
- X#include "inet_addr_fix"
- X#endif
- X
- Xint log_severity = SEVERITY; /* run-time adjustable */
- X
- X/* Try out a (daemon,client) pair */
- X
- Xtry(daemon, name, addr)
- Xchar *daemon;
- Xchar *name;
- Xchar *addr;
- X{
- X printf(" Daemon: %s\n", daemon);
- X printf(" Hostname: %s\n", name);
- X printf(" Address: %s\n", addr);
- X printf(" Access: %s\n",
- X hosts_ctl(daemon, name, addr, "you") ? "granted" : "denied");
- X}
- X
- X/* function to intercept the real shell_cmd() */
- X
- Xvoid shell_cmd(cmd, daemon, client)
- Xchar *cmd;
- Xchar *daemon;
- Xstruct from_host *client;
- X{
- X char buf[BUFSIZ];
- X int pid = getpid();
- X
- X percent_x(buf, sizeof(buf), cmd, daemon, client, pid);
- X printf(" Command: %s\n", buf);
- X}
- X
- X/* function to intercept the real process_options() */
- X
- Xprocess_options(options, daemon, client)
- Xchar *options;
- Xchar *daemon;
- Xstruct from_host *client;
- X{
- X char buf[BUFSIZ];
- X int pid = getpid();
- X
- X percent_x(buf, sizeof(buf), options, daemon, client, pid);
- X printf(" Options: %s\n", buf);
- X}
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X struct hostent *hp;
- X
- X#ifdef LOG_MAIL
- X openlog(argv[0], LOG_PID, FACILITY);
- X#else
- X openlog(argv[0], LOG_PID);
- X#endif
- X
- X /*
- X * Abuse inet_addr() to find out if a host name or address was specified.
- X *
- X * If a host address is specified, pretend that the host name lookup failed.
- X * This allows us to simulate the effect of host name lookup failures.
- X *
- X * If a host name is specified, insist that the address is known. The reason
- X * for giving up is that in real life, a host address is always
- X * available.
- X */
- X
- X if (argc != 3) {
- X fprintf(stderr, "usage: %s process_name host_name_or_address\n",
- X argv[0]);
- X return (1);
- X }
- X if (inet_addr(argv[2]) != INADDR_NONE) { /* address specified */
- X try(argv[1], FROM_UNKNOWN, argv[2]);
- X return (0);
- X }
- X if ((hp = gethostbyname(argv[2])) == 0) { /* address lookup fails */
- X fprintf(stderr, "host %s: address lookup failed\n", argv[2]);
- X return (1);
- X }
- X while (hp->h_addr_list[0]) /* name and address known */
- X try(argv[1], hp->h_name,
- X inet_ntoa(*(struct in_addr *) * hp->h_addr_list++));
- X return (0);
- X}
- X
- X#else
- X
- Xmain()
- X{
- X fprintf(stderr, "host access control is not enabled.\n");
- X return (1);
- X}
- X
- X#endif
- END_OF_try.c
- if test 3200 -ne `wc -c <try.c`; then
- echo shar: \"try.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f refuse.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"refuse.c\"
- else
- echo shar: Extracting \"refuse.c\" \(737 characters\)
- sed "s/^X//" >refuse.c <<'END_OF_refuse.c'
- X /*
- X * refuse() reports a refused connection, and takes the consequences: in
- X * case of a datagram-oriented service, the unread datagram is taken from
- X * the input queue (or inetd would see the same datagram again and again);
- X * the program is terminated.
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) refuse.c 1.2 92/06/11 22:21:34";
- X#endif
- X
- X/* System libraries. */
- X
- X#include <syslog.h>
- X
- X/* Local stuff. */
- X
- X#include "log_tcp.h"
- X
- X/* refuse - refuse request from bad host */
- X
- Xvoid refuse(client)
- Xstruct from_host *client;
- X{
- X syslog(LOG_WARNING, "refused connect from %s", hosts_info(client));
- X clean_exit(client);
- X /* NOTREACHED */
- X}
- END_OF_refuse.c
- if test 737 -ne `wc -c <refuse.c`; then
- echo shar: \"refuse.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f Makefile.dist -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"Makefile.dist\"
- else
- echo shar: Extracting \"Makefile.dist\" \(15575 characters\)
- sed "s/^X//" >Makefile.dist <<'END_OF_Makefile.dist'
- X# @(#) Makefile.dist 1.2 93/03/24 22:42:41
- X#
- X# If you did not already do so, copy the file Makefile.dist to Makefile
- X# and edit the copy, not the original. Have a copy of the README file at
- X# hand while editing. It gives some additional background.
- X#
- X# For your convenience, all configurable parameters have been moved into
- X# the Makefile, so that you do not have to hack the source files anymore.
- X#
- X# Some parameters must always be set to match the operating environment.
- X# Other parameter settings are a matter of taste. Their sections headings
- X# are labeled "(Optional)". The defaults correspond to the programs as
- X# documented in the manual pages.
- X
- X######################################################
- X# Choice between easy and advanced installation recipe
- X#
- X# According to the easy installation recipe in the README file, vendor-
- X# provided network daemons are moved to "some other" directory, and the
- X# tcpd wrapper fills in the "holes". For this mode of operation, the
- X# REAL_DAEMON_DIR macro should be set to the "some other" directory.
- X# Uncomment the appropriate line. The "..." is here for historical
- X# reasons only; you will probably want to use some other name. Watch out
- X# for the quotes and backslashes.
- X
- XREAL_DAEMON_DIR=\"/usr/etc/...\" # BSD 4.3 Ultrix 4.x SunOS 4.x
- X#REAL_DAEMON_DIR=\"/usr/sbin/...\" # SysV.4 Solaris 2.x
- X#REAL_DAEMON_DIR=\"/usr/libexec/...\" # BSD 4.4
- X
- X# According to the advanced installation recipe, vendor-provided daemons
- X# are left alone, and the inetd file is edited instead. In that case, the
- X# REAL_DAEMON_DIR macro should reflect the actual directory with (most of)
- X# your vendor-provided network daemons. Uncomment the appropriate line.
- X
- X#REAL_DAEMON_DIR=\"/usr/etc\" # BSD 4.3 Ultrix 4.x SunOS 4.x
- X#REAL_DAEMON_DIR=\"/usr/sbin\" # SysV.4 Solaris 2.x
- X#REAL_DAEMON_DIR=\"/usr/libexec\" # BSD 4.4
- X
- X#########################################################
- X# Differences between ranlib(1) and ar(1) implementations
- X#
- X# Some C compilers (Ultrix 4.x) insist that ranlib(1) be run on an object
- X# library; some don't care as long as the modules are in the right order;
- X# some systems don't even have a ranlib(1) command. SGI IRIX uses the 's'
- X# option to the 'ar' command instead. Make your choice.
- X
- XRANLIB = ranlib # have ranlib (BSD-ish UNIX)
- X#RANLIB = echo # no ranlib (SYSV-ish UNIX)
- X
- XARFLAGS = rv # OK for most systems
- X#ARFLAGS= rvs # ranlib flag for 'ar' on IRIX 4.0.x
- X
- X#######################################################
- X# Routines that are not present in the system libraries
- X#
- X# The strcasecmp.c file provided with this package comes from 4.3+BSD
- X# UNIX. The setenv.c module is a re-implementation of the 4.4 BSD one.
- X# strtok.c comes from 4.4BSD.
- X
- XAUX_OBJ = setenv.o # no setenv(3)
- X#AUX_OBJ= setenv.o strcasecmp.o # no setenv(3) and no strcasecmp(3)
- X#AUX_OBJ= setenv.o strcasecmp.o strtok.o
- X
- X# While building the file strcasecmp.o, the compiler may complain that
- X# u_char is undefined. Uncomment the following definition for a fix.
- X#
- X#UCHAR = -Du_char="unsigned char" # no u_char type
- X
- X# Uncomment the following if your C library has index/rindex/bcmp
- X# but does not provide the strchr/strrchr/memcmp routines. If that
- X# is the case, you probably also do not have strtok() (see above).
- X#
- X#STRINGS= -Dindex=strchr -Drindex=strrchr -Dmemcmp=bcmp
- X
- X###########################################
- X# Selection of non-default object libraries
- X#
- X# Many System-V versions require that you explicitly specify the networking
- X# libraries (for example, -lnet or -linet).
- X#
- X#LIBS = -lsocket -lnsl # SysV.4 Solaris 2.x
- X#LIBS = -lsun # IRIX
- X
- X#########################
- X# Ultrix-specific section
- X#
- X# Ultrix users may want to use the miscd wrapper, too. The Ultrix miscd
- X# implements among others the SYSTAT service which runs the WHO command,
- X# and thus provides a subset of the finger service. The very first wrapper
- X# application (in the early hours of May 20, 1990) was to monitor SYSTAT.
- X
- Xall: tcpd try # no Ultrix miscd
- X#all: tcpd try miscd # Ultrix, monitor systat etc. too
- X
- X#REAL_MISCD=\"/usr/etc/.../miscd\" # easy installation
- X#REAL_MISCD=\"/usr/etc/miscd\" # advanced installation
- X
- X################################
- X# System-specific compiler flags
- X#
- X# Apollo Domain/OS offers both bsd and sys5 environments, sometimes
- X# on the same machine. If your Apollo is primarily sys5.3 and also
- X# has bsd4.3, uncomment the following to build under bsd and run under
- X# either environment.
- X#
- X#SYSTYPE= -A run,any -A sys,any
- X
- X# For MIPS RISC/os 4_52.p3, uncomment the following definition.
- X#
- X#SYSTYPE= -sysname bsd43
- X
- X############################
- X# Working around system bugs
- X#
- X# Some versions of Apollo or SYSV.4 UNIX have a bug in the getpeername(2)
- X# routine. You may have this bug when the wrapper reports that all UDP
- X# connections come from address 0.0.0.0. Compile with -DGETPEERNAME_BUG
- X# for a workaround. The workaround does no harm on other systems. If in
- X# doubt, leave it in.
- X#
- X# Some System V versions (Solaris 2) have a problem in the recvfrom()
- X# emulation code. You may have this bug when the wrapper programs
- X# complain about "unexpected address family 0" when processing an UDP
- X# request. Compile with -DRECVFROM_BUG for a workaround. The workaround
- X# does no harm on other systems. If in doubt, leave it in.
- X#
- X# With some System V implementations (SCO UNIX 3.2v4), even compiling
- X# with -DRECVFROM_BUG does not solve the "address family 0" problem. If
- X# that is the case, compile with -DADDRESS_FAMILY_BUG instead.
- X#
- X# DG/UX 5.4.1 comes with an inet_ntoa() function that returns a structure
- X# instead of a long integer. Compile with -DINET_ADDR_BUG to work around
- X# this mutant behavour.
- X
- XBUGS = -DGETPEERNAME_BUG -DRECVFROM_BUG # -DADDRESS_FAMILY_BUG
- X
- X####################################################
- X# Whether or not your system has NIS (or YP) support
- X#
- X# If your system supports NIS or YP-style netgroups, enable the following
- X# macro definition. Netgroups are used only for host access control.
- X#
- X#NETGROUP= -DNETGROUP
- X
- X# End of the required configuration options; all other ones are optional.
- X#########################################################################
- X
- X################################################################
- X# Changing the default disposition of logfile records (Optional)
- X#
- X# By default, logfile entries are written to the same file as used for
- X# sendmail transaction logs. See your /etc/syslog.conf file for actual
- X# path names of logfiles. The tutorial section in the README file
- X# gives a brief introduction to the syslog daemon.
- X#
- X# Change the FACILITY definition below if you disagree with the default
- X# disposition. Some syslog versions (including Ultrix 4.x) do not provide
- X# this flexibility.
- X#
- X# If nothing shows up on your system, it may be that the syslog records
- X# are sent to a dedicated loghost. It may also be that no syslog daemon
- X# is running at all. The README file gives pointers to surrogate syslog
- X# implementations for systems that have no syslog library routines or
- X# no syslog daemons.
- X#
- X# The LOG_XXX names below are taken from the /usr/include/syslog.h file.
- X
- XFACILITY= LOG_MAIL # LOG_MAIL is what most sendmail daemons use
- X
- X# The syslog priority at which successful connections are logged.
- X
- XSEVERITY= LOG_INFO # LOG_INFO is normally not logged to the console
- X
- X#############################################
- X# Enabling remote username lookups (Optional)
- X#
- X# By default, the wrappers just report the remote host name (the host
- X# address if the host name lookup fails or times out). Username lookups
- X# require that the remote host runs a daemon that supports a RFC 931 like
- X# protocol. Remote user name lookups are not possible for UDP-based
- X# connections, and can cause noticeable delays with connections from
- X# non-UNIX PCs. On some systems, remote username lookups can trigger a
- X# kernel bug, causing loss of service. The README file gives details on
- X# how to find out if your system has that problem.
- X#
- X# Uncomment the following definition if the wrappers should always
- X# attempt to get the remote user name.
- X#
- X# The default username lookup timeout is 30 seconds.
- X#
- X#AUTH = -DRFC931_TIMEOUT=30 -DRFC931
- X
- X# The USER_AT_HOST feature does selective username lookups. It triggers
- X# on access control patterns of the form xxx@yyy. Until now, such
- X# patterns were not used, so that USER_AT_HOST does not break existing
- X# rules.
- X#
- X# The feature is not documented and is not yet intended for general use,
- X# because it can complicate the design of access control tables.
- X#
- X# With USER_AT_HOST enabled, remote username lookups are done only for
- X# user_pattern@host_pattern expressions in the access control files, but
- X# only when the host_pattern matches. Example: "ALL: @pcgroup ALL@ALL"
- X# avoids user name lookups for members of the pcgroup netgroup. The
- X# user_pattern syntax is identical to that of host_pattern, but "ALL"
- X# is usually the only user_pattern that makes sense.
- X#
- X# The default username lookup timeout is 30 seconds.
- X#
- X#AUTH = -DRFC931_TIMEOUT=30 -DUSER_AT_HOST
- X
- X########################################################
- X# Turning on experimental language extensions (Optional)
- X#
- X# Instead of the officially documented access control language, the
- X# software can be configured to implement a more experimental language
- X# that is easily extended. The experimental language is implemented by
- X# the "options.c" source module which also serves as its documentation.
- X
- XSTYLE = -DOPTIONS_STYLE=shell_cmd # The documented language
- X#STYLE = -DOPTIONS_STYLE=process_options # The experimental one
- X
- X######################################################
- X# Changing the default file protection mask (Optional)
- X#
- X# On many systems, network daemons and other system processes are started
- X# with a zero umask value, so that world-writable files may be produced.
- X# It is a good idea to edit your /etc/rc* files so that they begin with
- X# an explicit umask setting. On our site we use `umask 022' because it
- X# does not break anything yet gives adequate protection against tampering.
- X#
- X# The following macro specifies the default umask for processes run under
- X# control of the daemon wrappers. Comment it out only if you are certain
- X# that inetd and its children are started with a safe umask value.
- X
- XUMASK = -DDAEMON_UMASK=022
- X
- X#######################################
- X# Turning off access control (Optional)
- X#
- X# By default, host access control is enabled. To disable host access
- X# control, comment out the following definition. Host access control
- X# can also be turned off at runtime by providing no or empty access
- X# control tables.
- X
- XACCESS = -DHOSTS_ACCESS
- X
- X########################################################
- X# Changing the access control table pathnames (Optional)
- X#
- X# The HOSTS_ALLOW and HOSTS_DENY macros define where the programs will
- X# look for access control information. Watch out for the quotes and
- X# backslashes when you make changes.
- X
- XTABLES = -DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\"
- X
- X###########################################
- X# Turning off host NAME checking (Optional)
- X#
- X# By default, the software tries to protect against hosts that claim to
- X# have someone elses host name. This is relevant for network services
- X# whose authentication depends on host names, such as rsh and rlogin.
- X#
- X# With paranoid mode on, connections will be rejected when the host name
- X# does not match the host address. Connections will also be rejected when
- X# the host name cannot be verified because gethostbyname() fails.
- X#
- X# Comment out the following definition if you do not need this additional
- X# protection. If paranoid mode is off, and a host name check fails, the
- X# daemon wrappers will use only the host address, but your daemons may
- X# still use the host name.
- X
- XPARANOID= -DPARANOID
- X
- X#############################################
- X# Turning on host ADDRESS checking (Optional)
- X#
- X# Optionally, the software tries to protect against hosts that pretend to
- X# have someone elses host address. This is relevant for network services
- X# whose authentication depends on host names, such as rsh and rlogin,
- X# because the network address is used to look up the remote host name.
- X#
- X# The protection is effective only when the offending host claims to have
- X# a network address that lies outside its own network.
- X#
- X# My site has been running rlogind and rshd daemons that implement this
- X# feature for more than 2 years, and without any ill effects.
- X#
- X# This feature cannot be used with SunOS 4.x because of a kernel bug in
- X# the implementation of the getsockopt() system call. Kernel panics have
- X# been reported for SunOS 4.1.1 and SunOS 4.1.2. Symptoms are "BAD TRAP"
- X# and "Data fault" while executing the tcp_ctloutput() kernel function.
- X#
- X# Uncomment the following macro definition if your getsockopt() is OK.
- X#
- X# KILL_OPT= -DKILL_IP_OPTIONS
- X
- X## End configuration options
- X############################
- X
- XCFLAGS = -O -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
- X $(BUGS) $(SYSTYPE) $(AUTH) $(UMASK) -DREAL_MISCD=$(REAL_MISCD) \
- X -DREAL_DAEMON_DIR=$(REAL_DAEMON_DIR) $(STYLE) $(KILL_OPT) \
- X -DSEVERITY=$(SEVERITY) $(UCHAR) $(TABLES) $(STRINGS)
- X
- XLIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o hosts_info.o \
- X hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ) \
- X fromhost.o fix_options.o
- X
- XKIT = README miscd.c tcpd.c fromhost.c hosts_access.c shell_cmd.c \
- X log_tcp.h try.c refuse.c Makefile.dist hosts_access.5 strcasecmp.c \
- X BLURB rfc931.c tcpd.8 hosts_info.c hosts_access.3 hosts_ctl.c \
- X percent_x.c options.c clean_exit.c setenv.c patchlevel.h strtok.c \
- X fix_options.c inet_addr_fix
- X
- XLIB = libwrap.a
- X
- X$(LIB): $(LIB_OBJ)
- X rm -f $(LIB)
- X ar $(ARFLAGS) $(LIB) $(LIB_OBJ)
- X $(RANLIB) $(LIB)
- X
- Xtcpd: tcpd.o fromhost.o $(LIB)
- X $(CC) $(CFLAGS) -o $@ tcpd.o fromhost.o $(LIB) $(LIBS)
- X
- Xmiscd: miscd.o fromhost.o $(LIB)
- X $(CC) $(CFLAGS) -o $@ miscd.o fromhost.o $(LIB) $(LIBS)
- X
- Xtry: try.o $(LIB)
- X $(CC) $(CFLAGS) -o $@ try.o $(LIB) $(LIBS)
- X
- Xfromhost: fromhost.c log_tcp.h Makefile $(LIB)
- X $(CC) $(CFLAGS) -DTEST -o fromhost fromhost.c $(LIB) $(LIBS)
- X rm -f fromhost.o
- X
- Xshar: $(KIT)
- X @shar $(KIT)
- X
- Xkit: $(KIT)
- X @makekit $(KIT)
- X
- Xarchive:
- X $(ARCHIVE) $(KIT)
- X
- Xclean:
- X rm -f tcpd miscd try fromhost *.[oa] core
- X
- X# Enable all bells and whistles for linting.
- X
- Xlint: tcpd_lint miscd_lint try_lint
- X
- Xtcpd_lint:
- X lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DPARANOID -DNETGROUP \
- X -DGETPEERNAME_BUG -DDAEMON_UMASK=022 -DSEVERITY=$(SEVERITY) \
- X -DUSER_AT_HOST -DKILL_IP_OPTIONS -DOPTIONS_STYLE=process_options \
- X tcpd.c fromhost.c hosts_access.c shell_cmd.c refuse.c rfc931.c \
- X hosts_info.c percent_x.c clean_exit.c options.c setenv.c fix_options.c
- X
- Xmiscd_lint:
- X lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DPARANOID -DNETGROUP \
- X -DGETPEERNAME_BUG -DDAEMON_UMASK=022 -DSEVERITY=$(SEVERITY) \
- X -DUSER_AT_HOST -DKILL_IP_OPTIONS -DOPTIONS_STYLE=process_options \
- X miscd.c fromhost.c hosts_access.c shell_cmd.c refuse.c rfc931.c \
- X hosts_info.c percent_x.c clean_exit.c options.c setenv.c fix_options.c
- X
- Xtry_lint:
- X lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DNETGROUP try.c \
- X hosts_ctl.c hosts_access.c hosts_info.c percent_x.c
- X
- X# Compilation dependencies.
- X
- Xclean_exit.o: log_tcp.h Makefile
- Xfix_options.o: log_tcp.h Makefile
- Xfromhost.o: log_tcp.h Makefile
- Xhosts_access.o: log_tcp.h Makefile
- Xhosts_ctl.o: log_tcp.h Makefile
- Xhosts_info.o: log_tcp.h Makefile
- Xmiscd.o: patchlevel.h log_tcp.h Makefile
- Xoptions.o: log_tcp.h Makefile
- Xpercent_x.o: log_tcp.h Makefile
- Xrefuse.o: log_tcp.h Makefile
- Xrfc931.o: log_tcp.h Makefile
- Xshell_cmd.o: log_tcp.h Makefile
- Xtcpd.o: patchlevel.h log_tcp.h Makefile
- Xtry.o: log_tcp.h Makefile
- END_OF_Makefile.dist
- if test 15575 -ne `wc -c <Makefile.dist`; then
- echo shar: \"Makefile.dist\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f hosts_access.5 -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"hosts_access.5\"
- else
- echo shar: Extracting \"hosts_access.5\" \(9533 characters\)
- sed "s/^X//" >hosts_access.5 <<'END_OF_hosts_access.5'
- X.TH HOSTS_ACCESS 5
- X.SH NAME
- Xhosts_access \- format of host access control files
- X.SH DESCRIPTION
- XThis manual page describes a simple access control language that is
- Xbased on client (host name or address) and server (process name)
- Xpatterns. Examples are given at the end. The impatient reader can skip
- Xto the EXAMPLES section for a quick introduction.
- X.PP
- XIn the following text, \fIdaemon\fR is the the process name of a
- Xnetwork daemon process, and \fIclient\fR is the name and/or address of
- Xa host requesting service. Network daemon process names are specified
- Xin the inetd configuration file.
- X.SH ACCESS CONTROL FILES
- XThe access control software consults two files:
- X.IP o
- XAccess will be granted when a (daemon,client) pair matches an entry in
- Xthe \fI/etc/hosts.allow\fR file.
- X.IP o
- XOtherwise, access will be denied when a (daemon,client) pair matches an
- Xentry in the \fI/etc/hosts.deny\fR file.
- X.IP o
- XOtherwise, access will be granted.
- X.PP
- XA non-existing access control file is treated as if it were an empty
- Xfile. Thus, access control can be turned off by providing no access
- Xcontrol files.
- X.SH ACCESS CONTROL RULES
- XEach access control file consists of zero or more lines of text. These
- Xlines are processed in order of appearance. The search terminates when a
- Xmatch is found.
- X.IP o
- XA newline character is ignored when it is preceded by a backslash
- Xcharacter.
- X.IP o
- XBlank lines or lines that begin with a `#\' character are ignored.
- X.IP o
- XAll other lines should satisfy the following format, things between []
- Xbeing optional:
- X.sp
- X.ti +3
- Xdaemon_list : client_list [ : shell_command ]
- X.PP
- X\fIdaemon_list\fR is a list of one or more daemon process names
- X(argv[0] values) or wildcards (see below).
- X.PP
- X\fIclient_list\fR is a list
- Xof one or more host names, host addresses, patterns or wildcards (see
- Xbelow) that will be matched against the remote host name or address.
- X.PP
- XList elements should be separated by blanks and/or commas.
- X.PP
- XWith the exception of NIS (YP) netgroup lookups, all access control
- Xchecks are case insensitive.
- X.br
- X.ne 4
- X.SH PATTERNS
- XThe access control language implements the following patterns:
- X.IP o
- XA string that begins with a `.\' character. A client name or address
- Xis matched if its last components match the specified pattern. For
- Xexample, the pattern `.tue.nl\' matches the host name
- X`wzv.win.tue.nl\'.
- X.IP o
- XA string that ends with a `.\' character. A client name or address is
- Xmatched if its first fields match the given string. For example, the
- Xpattern `131.155.\' matches the address of (almost) every host on the
- XEind\%hoven University network (131.155.x.x).
- X.IP o
- XA string that begins with a `@\' character is treated as a netgroup
- Xname. Netgroups are usually supported on systems with NIS (formerly
- XYP) data bases. A client host name is matched if it is a (host) member
- Xof the specified netgroup.
- X.IP o
- XAn expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a
- X`net/mask\' pair. A client address is matched if `net\' is equal to the
- Xbitwise AND of the address and the `mask\'. For example, the net/mask
- Xpattern `131.155.72.0/255.255.254.0\' matches every address in the
- Xrange `131.155.72.0\' through `131.155.73.255\'.
- X.SH WILDCARDS
- XThe access control language supports explicit wildcards:
- X.IP ALL
- XIf this token appears in a daemon_list, it matches all network daemon
- Xprocess names. If the ALL token appears in a client_list, it matches
- Xall client names and addresses.
- X.IP LOCAL
- XMatches any string that does not contain a dot character.
- XTypical use is in client_lists.
- X.IP UNKNOWN
- XMatches any host whose name and/or address lookup failed. Should be
- Xused with care, because host names may also be unavailable due to
- Xtemporary name server problems.
- X.IP FAIL
- XLike the ALL wildcard, but causes the software to pretend that the scan
- Xof the current access control table fails. FAIL is being phased out; it
- Xwill become an undocumented feature. The EXCEPT operator (see below) is
- Xa much cleaner alternative.
- X.br
- X.ne 6
- X.SH OPERATORS
- X.IP EXCEPT
- XIntended use is of the form: `list_1 EXCEPT list_2\'; this construct
- Xmatches anything that matches \fIlist_1\fR unless it matches
- X\fIlist_2\fR. This construct can be used in daemon_lists and in
- Xclient_lists. The EXCEPT operator can be nested and is
- Xright-associative (just like C's assignment operator).
- X.br
- X.ne 6
- X.SH SHELL COMMANDS
- XIf the first-matched access control rule contains a shell command, that
- Xcommand is subjected to the following substitutions:
- X.IP %a
- Xexpands to the remote host address.
- X.IP %c
- Xexpands to client information: user@host, user@address, a host name, or
- Xjust an address, depending on how much information is available.
- X.IP %h
- Xexpands to the remote host name (or address, if the host name is
- Xunavailable).
- X.IP %d
- Xexpands to the daemon process name (argv[0] value).
- X.IP %p
- Xexpands to the daemon process id.
- X.IP %u
- Xexpands to the remote user name (or "unknown").
- X.IP %%
- Xexpands to a single `%\' character.
- X.PP
- XCharacters in % expansions that may confuse the shell are replaced by
- Xunderscores.
- XThe result is executed by a \fI/bin/sh\fR child process with standard
- Xinput, output and error connected to \fI/dev/null\fR. Specify an `&\'
- Xat the end of the command if you do not want to wait until it has
- Xcompleted.
- X.PP
- XShell commands should not rely on the PATH setting of the inetd.
- XInstead, they should use absolute path names, or they should begin with
- Xan explicit PATH=whatever statement.
- X.SH EXAMPLES
- XThe language is flexible enough that different types of access control
- Xpolicy can be expressed with a minimum of fuss. Although the language
- Xuses two access control tables, the most common policies can be
- Ximplemented with one of the tables being trivial or even empty.
- X.PP
- XWhen reading the examples below it is important to realize that the
- Xallow table is scanned before the deny table, that the search
- Xterminates when a match is found, and that access is granted when no
- Xmatch is found at all.
- X.PP
- XThe examples use host and domain names. They can be improved by
- Xincluding address and/or network/netmask information, to reduce the
- Ximpact of temporary name server lookup failures.
- X.SH MOSTLY CLOSED
- XIn this case, access is denied by default. Only explicitly authorized
- Xhosts are permitted access.
- X.PP
- XThe default policy (no access) is implemented with a trivial deny
- Xfile:
- X.PP
- X.ne 2
- X/etc/hosts.deny:
- X.in +3
- XALL: ALL
- X.PP
- XThis denies all service to all hosts, unless they are permitted access
- Xby entries in the allow file.
- X.PP
- XThe explicitly authorized hosts are listed in the allow file.
- XFor example:
- X.PP
- X.ne 2
- X/etc/hosts.allow:
- X.in +3
- XALL: LOCAL @some_netgroup
- X.br
- XALL: .foobar.edu EXCEPT terminalserver.foobar.edu
- X.PP
- XThe first rule permits access to all services from hosts in the local
- Xdomain (no `.\' in the host name) and from members of the
- X\fIsome_netgroup\fP netgroup. The second rule permits access to all
- Xservices from all hosts in the \fI.foobar.edu\fP domain, with the
- Xexception of \fIterminalserver.foobar.edu\fP.
- X.SH MOSTLY OPEN
- XHere, access is granted by default; only explicitly specified hosts are
- Xrefused service.
- X.PP
- XThe default policy (access granted) makes the allow file redundant so
- Xthat it can be omitted. The explicitly non-authorized hosts are listed
- Xin the deny file. For example:
- X.PP
- X/etc/hosts.deny:
- X.in +3
- XALL: some.host.name, .some.domain
- X.br
- XALL EXCEPT in.fingerd: other.host.name, .other.domain
- X.PP
- XThe first rule denies some hosts all services; the second rule still
- Xpermits finger requests from other hosts.
- X.SH BOOBY TRAPS
- XThe next example permits tftp requests from hosts in the local domain.
- XRequests from any other hosts are denied. Instead of the requested
- Xfile, a finger probe is sent to the offending host. The result is
- Xmailed to the superuser.
- X.PP
- X.ne 2
- X/etc/hosts.allow:
- X.in +3
- X.nf
- Xin.tftpd: LOCAL, .my.domain
- X.PP
- X.ne 2
- X/etc/hosts.deny:
- X.in +3
- X.nf
- Xin.tftpd: ALL: (/usr/ucb/finger -l @%h | /usr/ucb/mail -s %d-%h root) &
- X.fi
- X.PP
- XThe expansion of the %h (remote host) and %d (service name) sequences
- Xis described in the section on shell commands.
- X.PP
- XWarning: do not booby-trap your finger daemon, unless you are prepared
- Xfor infinite finger loops.
- X.PP
- XOn network firewall systems this trick can be carried even further.
- XThe typical network firewall only provides a limited set of services to
- Xthe outer world. All other services can be "bugged" just like the above
- Xtftp example. The result is an excellent early-warning system.
- X.br
- X.ne 4
- X.SH DIAGNOSTICS
- XAn error is reported when a syntax error is found in a host access
- Xcontrol rule; when the length of an access control rule exceeds the
- Xcapacity of an internal buffer; when an access control rule is not
- Xterminated by a newline character; when the result of %<character>
- Xexpansion would overflow an internal buffer; when a system call fails
- Xthat shouldn\'t. All problems are reported via the syslog daemon.
- X.SH FILES
- X.na
- X.nf
- X/etc/hosts.allow, (daemon,client) pairs that are granted access.
- X/etc/hosts.deny, (daemon,client) pairs that are denied access.
- X.ad
- X.fi
- X.SH SEE ALSO
- Xtcpd(8) tcp/ip daemon wrapper program.
- X.SH BUGS
- XIf a name server lookup times out, the host name will not be available
- Xto the access control software, even though the host is registered.
- X.PP
- XDomain name server lookups are case insensitive; NIS (formerly YP)
- Xnetgroup lookups are case sensitive.
- X.SH AUTHOR
- X.na
- X.nf
- XWietse Venema (wietse@wzv.win.tue.nl)
- XDepartment of Mathematics and Computing Science
- XEindhoven University of Technology
- XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X\" @(#) hosts_access.5 1.11 93/03/07 22:47:47
- END_OF_hosts_access.5
- if test 9533 -ne `wc -c <hosts_access.5`; then
- echo shar: \"hosts_access.5\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f strcasecmp.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"strcasecmp.c\"
- else
- echo shar: Extracting \"strcasecmp.c\" \(3767 characters\)
- sed "s/^X//" >strcasecmp.c <<'END_OF_strcasecmp.c'
- X/*
- X * Copyright (c) 1987 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Berkeley. The name of the
- X * University may not be used to endorse or promote products derived
- X * from this software without specific prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X */
- X
- X#if defined(LIBC_SCCS) && !defined(lint)
- Xstatic char sccsid[] = "@(#)strcasecmp.c 5.6 (Berkeley) 6/27/88";
- X#endif /* LIBC_SCCS and not lint */
- X
- X#include <sys/types.h>
- X
- X/*
- X * This array is designed for mapping upper and lower case letter
- X * together for a case independent comparison. The mappings are
- X * based upon ascii character sequences.
- X */
- Xstatic u_char charmap[] = {
- X '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- X '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- X '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- X '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- X '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- X '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- X '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- X '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- X '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- X '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- X '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- X '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
- X '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- X '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- X '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- X '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
- X '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- X '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- X '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- X '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- X '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- X '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- X '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- X '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- X '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- X '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- X '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- X '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
- X '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- X '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- X '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- X '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
- X};
- X
- Xstrcasecmp(s1, s2)
- X char *s1, *s2;
- X{
- X register u_char *cm = charmap,
- X *us1 = (u_char *)s1,
- X *us2 = (u_char *)s2;
- X
- X while (cm[*us1] == cm[*us2++])
- X if (*us1++ == '\0')
- X return(0);
- X return(cm[*us1] - cm[*--us2]);
- X}
- X
- Xstrncasecmp(s1, s2, n)
- X char *s1, *s2;
- X register int n;
- X{
- X register u_char *cm = charmap,
- X *us1 = (u_char *)s1,
- X *us2 = (u_char *)s2;
- X
- X while (--n >= 0 && cm[*us1] == cm[*us2++])
- X if (*us1++ == '\0')
- X return(0);
- X return(n < 0 ? 0 : cm[*us1] - cm[*--us2]);
- X}
- END_OF_strcasecmp.c
- if test 3767 -ne `wc -c <strcasecmp.c`; then
- echo shar: \"strcasecmp.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f BLURB -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"BLURB\"
- else
- echo shar: Extracting \"BLURB\" \(2068 characters\)
- sed "s/^X//" >BLURB <<'END_OF_BLURB'
- X@(#) BLURB 1.8 93/03/24 22:42:37
- X
- XWith the programs that come with this kit you can monitor incoming
- Xrequests for IP services such as TFTP, EXEC, FTP, RSH, TELNET, RLOGIN,
- XFINGER, SYSTAT, and many others.
- X
- XOptional features are: access control based on pattern matching; remote
- Xusername lookup using the RFC 931 protocol; protection against attacks
- Xfrom hosts that pretend to have someone elses name; protection against
- Xattacks from hosts that pretend to have someone elses network address.
- X
- XThe programs can be installed without requiring any changes to existing
- Xsoftware or configuration files. By default, they just log the remote
- Xhost name and do some sanity checks on the origin the request. No
- Xinformation is exchanged with the remote client process.
- X
- XThe most notable differences with respect to the previous release are:
- X
- X - Optional protection against attacks from hosts that pretend to
- X have someone elses network address. For example, the address of a
- X trusted host within your own network.
- X
- X - The access control language has been extended with a simple but
- X powerful operator that greatly simplifies the design of rule sets
- X (ALL: .foo.edu EXCEPT dialup.foo.edu). Blank lines are permitted,
- X and long lines can be continued with backslash-newline.
- X
- X - All configurable stuff, including path names, has been moved into
- X the Makefile so that you no longer have to hack source code to just
- X configure the programs.
- X
- X - Ported to Solaris 2. TLI-based applications not yet supported.
- X Several workarounds for System V bugs.
- X
- X - A small loophole in the netgroup lookup code was closed, and the
- X remote username lookup code was made more portable.
- X
- X - Still more documentation. The README file now provides tutorial
- X sections with introductions to client, server, inetd and syslogd.
- X
- XThe default mode of operation should be backwards compatible with
- Xearlier versions.
- X
- X Wietse Venema (wietse@wzv.win.tue.nl),
- X Department of Mathematics and Computing Science,
- X Eindhoven University of Technology,
- X The Netherlands.
- END_OF_BLURB
- if test 2068 -ne `wc -c <BLURB`; then
- echo shar: \"BLURB\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f rfc931.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"rfc931.c\"
- else
- echo shar: Extracting \"rfc931.c\" \(3825 characters\)
- sed "s/^X//" >rfc931.c <<'END_OF_rfc931.c'
- X /*
- X * rfc931_user() speaks a common subset of the RFC 931, AUTH, TAP and IDENT
- X * protocols. It consults an RFC 931 etc. compatible daemon on the client
- X * host to look up the remote user name. The information should not be used
- X * for authentication purposes.
- X *
- X * Diagnostics are reported through syslog(3).
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X *
- X * Inspired by the authutil package (comp.sources.unix volume 22) by Dan
- X * Bernstein (brnstnd@kramden.acf.nyu.edu).
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) rfc931.c 1.4 93/03/07 22:47:52";
- X#endif
- X
- X#include <stdio.h>
- X#include <syslog.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <setjmp.h>
- X#include <signal.h>
- X
- X#include "log_tcp.h"
- X
- X#define RFC931_PORT 113 /* Semi-well-known port */
- X
- X#ifndef RFC931_TIMEOUT
- X#define RFC931_TIMEOUT 30 /* wait for at most 30 seconds */
- X#endif
- X
- Xextern char *strchr();
- Xextern char *inet_ntoa();
- X
- Xstatic jmp_buf timebuf;
- X
- X/* timeout - handle timeouts */
- X
- Xstatic void timeout(sig)
- Xint sig;
- X{
- X longjmp(timebuf, sig);
- X}
- X
- X/* rfc931_name - return remote user name */
- X
- Xchar *rfc931_name(there)
- Xstruct sockaddr_in *there; /* remote link information */
- X{
- X struct sockaddr_in here; /* local link information */
- X struct sockaddr_in sin; /* for talking to RFC931 daemon */
- X int length;
- X int s;
- X unsigned remote;
- X unsigned local;
- X static char user[256]; /* XXX */
- X char buffer[512]; /* YYY */
- X FILE *fp;
- X char *cp;
- X char *result = FROM_UNKNOWN;
- X
- X /* Find out local address and port number of stdin. */
- X
- X length = sizeof(here);
- X if (getsockname(0, (struct sockaddr *) & here, &length) == -1) {
- X syslog(LOG_ERR, "getsockname: %m");
- X return (result);
- X }
- X
- X /*
- X * The socket that will be used for user name lookups should be bound to
- X * the same local IP address as stdin. This will automagically happen on
- X * hosts that have only one IP network address. When the local host has
- X * more than one IP network address, we must do an explicit bind() call.
- X */
- X
- X if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- X return (result);
- X
- X sin = here;
- X sin.sin_port = 0;
- X if (bind(s, (struct sockaddr *) & sin, sizeof sin) < 0) {
- X syslog(LOG_ERR, "bind: %s: %m", inet_ntoa(here.sin_addr));
- X return (result);
- X }
- X /* Set up timer so we won't get stuck. */
- X
- X signal(SIGALRM, timeout);
- X if (setjmp(timebuf)) {
- X close(s); /* not: fclose(fp) */
- X return (result);
- X }
- X alarm(RFC931_TIMEOUT);
- X
- X /* Connect to the RFC931 daemon. */
- X
- X sin = *there;
- X sin.sin_port = htons(RFC931_PORT);
- X if (connect(s, (struct sockaddr *) & sin, sizeof(sin)) == -1
- X || (fp = fdopen(s, "w+")) == 0) {
- X close(s);
- X alarm(0);
- X return (result);
- X }
- X
- X /*
- X * Use unbuffered I/O or we may read back our own query. setbuf() must be
- X * called before doing any I/O on the stream. Thanks for the reminder,
- X * Paul Kranenburg <pk@cs.few.eur.nl>!
- X */
- X
- X setbuf(fp, (char *) 0);
- X
- X /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */
- X
- X fprintf(fp, "%u,%u\r\n", ntohs(there->sin_port), ntohs(here.sin_port));
- X fflush(fp);
- X
- X /*
- X * Read response from server. Use fgets()/sscanf() instead of fscanf()
- X * because there is no buffer for pushback. Thanks, Chris Turbeville
- X * <turbo@cse.uta.edu>.
- X */
- X
- X if (fgets(buffer, sizeof(buffer), fp) != 0
- X && ferror(fp) == 0 && feof(fp) == 0
- X && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
- X &remote, &local, user) == 3
- X && ntohs(there->sin_port) == remote
- X && ntohs(here.sin_port) == local) {
- X /* Strip trailing carriage return. */
- X
- X if (cp = strchr(user, '\r'))
- X *cp = 0;
- X result = user;
- X }
- X alarm(0);
- X fclose(fp);
- X return (result);
- X}
- END_OF_rfc931.c
- if test 3825 -ne `wc -c <rfc931.c`; then
- echo shar: \"rfc931.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f tcpd.8 -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"tcpd.8\"
- else
- echo shar: Extracting \"tcpd.8\" \(6757 characters\)
- sed "s/^X//" >tcpd.8 <<'END_OF_tcpd.8'
- X.TH TCPD 8
- X.SH NAME
- Xtcpd \- access control facility for internet services
- X.SH DESCRIPTION
- X.PP
- XThe \fItcpd\fR program can be set up to monitor incoming requests for
- X\fItelnet\fR, \fIfinger\fR, \fIftp\fR, \fIexec\fR, \fIrsh\fR,
- X\fIrlogin\fR, \fItftp\fR, \fItalk\fR, \fIcomsat\fR and other services
- Xthat have a one-to-one mapping onto executable files.
- X.PP
- XOperation is as follows: whenever a request for internet service
- Xarrives, the \fIinetd\fP daemon is tricked into running the \fItcpd\fP
- Xprogram instead of the desired server. \fItcpd\fP logs the request and
- Xdoes some additional checks. When all is well, \fItcpd\fP runs the
- Xappropriate server program and goes away.
- X.PP
- XOptional features are: pattern-based access control, patterns, remote
- Xusername lookups with the RFC 931 protocol, protection against hosts
- Xthat pretend to have someone elses host name, and protection against
- Xhosts that pretend to have someone elses network address.
- X.SH LOGGING
- XConnections that are monitored by
- X.I tcpd
- Xare reported through the \fIsyslog\fR(3) facility. Each record contains
- Xa time stamp, the remote host name and the name of the service
- Xrequested. The information can be useful to detect unwanted activities,
- Xespecially when logfile information from several hosts is merged.
- X.PP
- XIn order to find out where your logs are going, examine the syslog
- Xconfiguration file, usually /etc/syslog.conf.
- X.SH ACCESS CONTROL
- XOptionally,
- X.I tcpd
- Xsupports a simple form of access control that is based on pattern
- Xmatching. The access-control software provides hooks for the execution
- Xof shell commands when a pattern fires. For details, see the
- X\fIhosts_access\fR(5) manual page.
- X.SH HOST NAME VERIFICATION
- XThe authentication scheme of some protocols (\fIrlogin, rsh\fR) relies
- Xon host names. Some implementations believe the host name that they get
- Xfrom any random name server; other implementations are more careful but
- Xuse a flawed algorithm.
- X.PP
- X.I tcpd
- Xverifies the remote host name that is returned by the address->name DNS
- Xserver by looking at the host name and address that are returned by the
- Xname->address DNS server. If any discrepancy is detected,
- X.I tcpd
- Xconcludes that it is dealing with a host that pretends to have someone
- Xelses host name.
- X.PP
- XIf the sources are compiled with the \*QPARANOID\*U option,
- X.I tcpd
- Xwill drop the connection in case of a host name/address mismatch.
- XOtherwise,
- X.I tcpd
- Xjust pretends that host name lookup failed when logging the connection
- Xand consulting the optional access control tables.
- X.SH HOST ADDRESS SPOOFING
- XBy default,
- X.I tcpd
- Xdisables source-routing socket options on every connection that it
- Xdeals with. This will take care of most attacks from hosts that pretend
- Xto have an address that belongs to someone elses network. UDP services
- Xdo not benefit from this protection.
- X.SH RFC 931
- XWhen RFC 931 lookups are enabled (compile-time option) \fItcpd\fR will
- Xattempt to establish the name of the remote user. This will succeed
- Xonly if the client host runs an RFC 931-compliant daemon. Remote user
- Xname lookups will not work for datagram-oriented connections, and may
- Xcause noticeable delays in the case of connections from PCs.
- X.SH EXAMPLES
- XThe details of using \fItcpd\fR depend on pathname information that was
- Xcompiled into the program.
- X.SH EXAMPLE 1
- XThis example applies when \fItcpd\fR expects that the original network
- Xdaemons will be moved to a "secret" place.
- X.PP
- XIn order to monitor access to the \fIfinger\fR service, move the
- Xoriginal finger daemon to the "secret" place and install tcpd in the
- Xplace of the original finger daemon. No changes are required to
- Xconfiguration files.
- X.nf
- X.sp
- X.in +5
- X# mkdir /secret/place
- X# mv /usr/etc/in.fingerd /secret/place
- X# cp tcpd /usr/etc/in.fingerd
- X.fi
- X.PP
- XThe example assumes that the network daemons live in /usr/etc. On some
- Xsystems, network daemons live in /usr/sbin or in /usr/libexec, or have
- Xno `in.\' prefix to their name.
- X.SH EXAMPLE 2
- XThis example applies when \fItcpd\fR expects that the network daemons
- Xare left in their original place.
- X.PP
- XIn order to monitor access to the \fIfinger\fR service, perform the
- Xfollowing edits on the \fIinetd\fR configuration file (usually
- X\fI/etc/inetd.conf\fR or \fI/etc/inet/inetd.conf\fR):
- X.nf
- X.sp
- X.ti +5
- Xfinger stream tcp nowait nobody /usr/etc/in.fingerd in.fingerd
- X.sp
- Xbecomes:
- X.sp
- X.ti +5
- Xfinger stream tcp nowait nobody /some/where/tcpd in.fingerd
- X.sp
- X.fi
- X.PP
- XThe example assumes that the network daemons live in /usr/etc. On some
- Xsystems, network daemons live in /usr/sbin or in /usr/libexec, the
- Xdaemons have no `in.\' prefix to their name, or there is no userid
- Xfield in the inetd configuration file.
- X.PP
- XSimilar changes will be needed for the other services that are to be
- Xcovered by \fItcpd\fR. Send a `kill -HUP\' to the \fIinetd\fR(8)
- Xprocess to make the changes effective.
- X.SH EXAMPLE 3
- XIn the case of daemons that do not live in a common directory ("secret"
- Xor otherwise), edit the \fIinetd\fR configuration file so that it
- Xspecifies an absolute path name for the process name field. For example:
- X.nf
- X.sp
- X ntalk dgram udp wait root /some/where/tcpd /usr/local/lib/ntalkd
- X.sp
- X.fi
- X.PP
- XOnly the last component (ntalkd) of the process name will be used for
- Xaccess control and logging.
- X.SH BUGS
- XSome UDP (and RPC) daemons linger around for a while after they have
- Xfinished their work, in case another request comes in. In the inetd
- Xconfiguration file these services are registered with the \fIwait\fR
- Xoption. Only the request that started such a daemon will be logged.
- X.PP
- XThe program does not work with RPC services over TCP. These services
- Xare registered as \fIrpc/tcp\fR in the inetd configuration file. The
- Xonly non-trivial service that is affected by this limitation is
- X\fIrexd\fR, which is used by the \fIon(1)\fR command. This is no great
- Xloss. On most systems, \fIrexd\fR is less secure than a wildcard in
- X/etc/hosts.equiv.
- X.PP
- XRPC broadcast requests (for example: \fIrwall, rup, rusers\fR) always
- Xappear to come from the responding host. What happens is that the
- Xclient broadcasts the request to all \fIportmap\fR daemons on its
- Xnetwork; each \fIportmap\fR daemon forwards the request to a local
- Xdaemon. As far as the \fIrwall\fR etc. daemons know, the request comes
- Xfrom the local host.
- X.SH FILES
- X.PP
- XThe default locations of the host access control tables are:
- X.PP
- X/etc/hosts.allow
- X.br
- X/etc/hosts.deny
- X.SH SEE ALSO
- X.na
- X.nf
- Xhosts_access(5), format of the tcpd access control tables.
- Xsyslog.conf(5), format of the syslogd control file.
- Xinetd.conf(5), format of the inetd control file.
- X.SH AUTHORS
- X.na
- X.nf
- XWietse Venema (wietse@wzv.win.tue.nl),
- XDepartment of Mathematics and Computing Science,
- XEindhoven University of Technology,
- XThe Netherlands.
- X\" @(#) tcpd.8 1.2 93/03/07 22:47:54
- END_OF_tcpd.8
- if test 6757 -ne `wc -c <tcpd.8`; then
- echo shar: \"tcpd.8\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f hosts_info.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"hosts_info.c\"
- else
- echo shar: Extracting \"hosts_info.c\" \(788 characters\)
- sed "s/^X//" >hosts_info.c <<'END_OF_hosts_info.c'
- X /*
- X * hosts_info() returns a string with as much information about the origin
- X * of a connection as we have: the user name, if known, and the host name,
- X * or the host address if the name is not available.
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) hosts_info.c 1.1 92/06/11 22:21:44";
- X#endif
- X
- X#include <stdio.h>
- X
- X#include "log_tcp.h"
- X
- X/* hosts_info - return string with as much about the client as we know */
- X
- Xchar *hosts_info(client)
- Xstruct from_host *client;
- X{
- X static char buf[BUFSIZ]; /* XXX */
- X
- X if (client->user[0] && strcmp(client->user, FROM_UNKNOWN)) {
- X sprintf(buf, "%s@%s", client->user, FROM_HOST(client));
- X return (buf);
- X } else {
- X return (FROM_HOST(client));
- X }
- X}
- END_OF_hosts_info.c
- if test 788 -ne `wc -c <hosts_info.c`; then
- echo shar: \"hosts_info.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f hosts_access.3 -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"hosts_access.3\"
- else
- echo shar: Extracting \"hosts_access.3\" \(2018 characters\)
- sed "s/^X//" >hosts_access.3 <<'END_OF_hosts_access.3'
- X.TH HOSTS_ACCESS 3
- X.SH
- Xhosts_access, hosts_ctl \- access control library
- X.SH SYNOPSIS
- X.nf
- X#include "log_tcp.h"
- X
- Xint hosts_access(daemon, client)
- Xchar *daemon;
- Xstruct from_host *client;
- X
- Xint hosts_ctl(daemon, client_name, client_addr, client_user)
- Xchar *daemon;
- Xchar *client_host;
- Xchar *client_addr;
- Xchar *client_user;
- X.fi
- X.SH DESCRIPTION
- XThe routines described in this document are part of the \fIlibwrap.a\fR
- Xlibrary. They implement a pattern-based access control language with
- Xoptional shell commands that are executed when a pattern fires.
- X.PP
- XIn all cases, the daemon argument should specify a daemon process name
- X(argv[0] value). The client host address should be a valid address, or
- XFROM_UNKNOWN if address lookup failed. The client host name and user
- Xname should be empty strings if no information is available,
- XFROM_UNKNOWN if lookup failed, or an actual host or user name.
- X.PP
- Xhosts_access() consults the access control tables described in the
- X\fIhosts_access(5)\fR manual page. If a match is found, an optional
- Xshell command is executed and the search terminates. hosts_access()
- Xreturns zero if access should be denied.
- X.PP
- Xhosts_ctl() is a wrapper around the hosts_access() routine with a
- Xperhaps more convenient interface. hosts_ctl() returns zero if access
- Xshould be denied.
- X.SH DIAGNOSTICS
- XProblems are reported via the syslog daemon.
- X.SH SEE ALSO
- Xhosts_access(5), format of the access control tables.
- X.SH FILES
- X/etc/hosts.access, /etc/hosts.deny, access control tables.
- X.SH BUGS
- XThe functions described here do not make copies of their string-valued
- Xarguments. Beware of data from functions that overwrite their results
- Xupon each call.
- X.sp
- Xhosts_access() uses the strtok() library function. This may interfere
- Xwith other code that relies on strtok().
- X.SH AUTHOR
- X.na
- X.nf
- XWietse Venema (wietse@wzv.win.tue.nl)
- XDepartment of Mathematics and Computing Science
- XEindhoven University of Technology
- XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X\" @(#) hosts_access.3 1.1 92/06/11 22:21:45
- END_OF_hosts_access.3
- if test 2018 -ne `wc -c <hosts_access.3`; then
- echo shar: \"hosts_access.3\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f hosts_ctl.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"hosts_ctl.c\"
- else
- echo shar: Extracting \"hosts_ctl.c\" \(969 characters\)
- sed "s/^X//" >hosts_ctl.c <<'END_OF_hosts_ctl.c'
- X /*
- X * hosts_ctl() combines the most common applications of the host access
- X * control library. routine. It bundles its arguments into a from_host
- X * structure, then calls the hosts_access() access control checker. The host
- X * name and user name arguments should be empty strings, "unknown" or real
- X * data. if a match is found, the optional shell command is executed.
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) hosts_ctl.c 1.1 92/06/11 22:21:48";
- X#endif
- X
- X#include <stdio.h>
- X
- X#include "log_tcp.h"
- X
- X/* hosts_ctl - general interface for the hosts_access() routine */
- X
- Xint hosts_ctl(daemon, name, addr, user)
- Xchar *daemon;
- Xchar *name;
- Xchar *addr;
- Xchar *user;
- X{
- X struct from_host client;
- X static struct from_host zeros;
- X
- X client = zeros;
- X client.name = name;
- X client.addr = addr;
- X client.user = user;
- X
- X return (hosts_access(daemon, &client));
- X}
- END_OF_hosts_ctl.c
- if test 969 -ne `wc -c <hosts_ctl.c`; then
- echo shar: \"hosts_ctl.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f percent_x.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"percent_x.c\"
- else
- echo shar: Extracting \"percent_x.c\" \(2603 characters\)
- sed "s/^X//" >percent_x.c <<'END_OF_percent_x.c'
- X /*
- X * percent_x() takes a string and performs %a (host address), %c (client
- X * info), %h (host name or address), %d (daemon name), %p (process id) and
- X * %u (user name) substitutions. It aborts the program when the result of
- X * expansion would overflow the output buffer. Because the result of %<char>
- X * expansion is typically passed on to a shell process, characters that may
- X * confuse the shell are replaced by underscores.
- X *
- X * Diagnostics are reported through syslog(3).
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) percent_x.c 1.2 92/08/24 21:46:22";
- X#endif
- X
- X/* System libraries. */
- X
- X#include <stdio.h>
- X#include <syslog.h>
- X
- Xextern char *strncpy();
- Xextern char *strchr();
- Xextern void exit();
- X
- X/* Local stuff. */
- X
- X#include "log_tcp.h"
- X
- X/* percent_x - do %<char> expansion, abort if result buffer is too small */
- X
- Xvoid percent_x(result, result_len, str, daemon, client, pid)
- Xchar *result;
- Xint result_len;
- Xchar *str;
- Xchar *daemon;
- Xstruct from_host *client;
- Xint pid;
- X{
- X char *end = result + result_len - 1; /* end of result buffer */
- X char *expansion;
- X int expansion_len;
- X char pid_buf[10];
- X static char ok_chars[] = "1234567890!@%-_=+\\:,./\
- Xabcdefghijklmnopqrstuvwxyz\
- XABCDEFGHIJKLMNOPQRSTUVWXYZ";
- X char *cp;
- X
- X /*
- X * %a becomes the client address; %c all user and host information we
- X * have about the client; %d the daemon process name; %h the client host
- X * name or address; %p the daemon process id; %u the remote user name; %%
- X * becomes a %, and %other is ignored. We terminate with a diagnostic if
- X * we would overflow the result buffer. Characters that may confuse the
- X * shell are mapped to underscores.
- X */
- X
- X while (*str) {
- X if (*str == '%') {
- X str++;
- X expansion =
- X *str == 'a' ? (str++, client->addr) :
- X *str == 'c' ? (str++, hosts_info(client)) :
- X *str == 'd' ? (str++, daemon) :
- X *str == 'h' ? (str++, FROM_HOST(client)) :
- X *str == 'p' ? (str++, sprintf(pid_buf, "%d", pid), pid_buf) :
- X *str == 'u' ? (str++, client->user) :
- X *str == '%' ? (str++, "%") :
- X *str == 0 ? "" : (str++, "");
- X expansion_len = strlen(expansion);
- X for (cp = expansion; *cp; cp++)
- X if (strchr(ok_chars, *cp) == 0)
- X *cp = '_';
- X } else {
- X expansion = str++;
- X expansion_len = 1;
- X }
- X if (result + expansion_len >= end) {
- X syslog(LOG_ERR, "shell command too long: %30s...", result);
- X exit(0);
- X }
- X strncpy(result, expansion, expansion_len);
- X result += expansion_len;
- X }
- X *result = 0;
- X}
- END_OF_percent_x.c
- if test 2603 -ne `wc -c <percent_x.c`; then
- echo shar: \"percent_x.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f options.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"options.c\"
- else
- echo shar: Extracting \"options.c\" \(10084 characters\)
- sed "s/^X//" >options.c <<'END_OF_options.c'
- X /*
- X * General skeleton for adding options to the access control language. The
- X * Makefile describes how this alternative language is enabled. Shell
- X * commands will still be available, be it with a slightly different syntax.
- X *
- X * The code uses a slightly different format of access control rules. It
- X * assumes that an access control rule looks like this:
- X *
- X * daemon_list : client_list : option : option ...
- X *
- X * An option is of the form "keyword" or "keyword = value". Option fields are
- X * processed from left to right. Blanks around keywords, "=" and values are
- X * optional. Blanks within values are left alone.
- X *
- X * Diagnostics are reported through syslog(3).
- X *
- X * Examples of options that are already implemented by the current skeleton:
- X *
- X * user = nobody
- X *
- X * Causes the process to switch its user id to that of "nobody". This normally
- X * requires root privilege.
- X *
- X * group = tty
- X *
- X * Causes the process to change its group id to that of the "tty" group. In
- X * order to switch both user and group ids you should normally switch the
- X * group id before switching the user id.
- X *
- X * setenv = name value
- X *
- X * places a name,value pair into the environment. The value is subjected to
- X * %<character> expansions.
- X *
- X * spawn = (/usr/ucb/finger -l @%h | /usr/ucb/mail root) &
- X *
- X * Executes (in a background child process) the shell command "finger -l @%h |
- X * mail root" after doing the %<character> expansions described in the
- X * hosts_access(5) manual page. The command is executed with stdin, stdout
- X * and stderr connected to the null device. Because options are processed in
- X * order, multiple spawn comands can be specified within the same access
- X * control rule, though "spawn = command1; command2" would be more
- X * efficient.
- X *
- X * in.ftpd : ... : twist = /bin/echo 421 Some customized bounce message
- X *
- X * Sends some custmized bounce message to the remote client instead of running
- X * the real ftp daemon. The command is subjected to %<character> expansion
- X * before execution by /bin/sh. Stdin, stdout and stderr are connected to the
- X * remote client process. The twist'ed command overlays the current process;
- X * it makes no sense to specify other options on the same line after a
- X * "twist". The "twist" option was inspired by Dan Bernstein's shuctl daemon
- X * wrapper control language.
- X *
- X * umask = value
- X *
- X * Sets the process file creation mask. Value must be an octal number.
- X *
- X * If you compile with -DRFC_OPTION, code is enabled for the following option
- X * that does selective rfc931 lookups.
- X *
- X * rfc931
- X *
- X * Causes the daemon front ends to look up the remote user name with the RFC
- X * 931 protocol.
- X *
- X * Warnings:
- X *
- X * This module uses the non-reentrant strtok() library routine. The options
- X * argument to process_options() is destroyed.
- X *
- X * There cannot be a ":" character in keywords or values. Backslash sequences
- X * are not yet recognized.
- X *
- X * In case of UDP connections, do not "twist" commands that use the standard
- X * I/O or read(2)/write(2) routines to communicate with the client process;
- X * UDP requires other communications primitives.
- X *
- X * In case of errors, use clean_exit() instead of directly calling exit(), or
- X * your inetd may loop on an UDP request.
- X */
- X
- X/* System libraries. */
- X
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#include <sys/socket.h>
- X#include <sys/stat.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <stdio.h>
- X#include <syslog.h>
- X#include <pwd.h>
- X#include <grp.h>
- X#include <ctype.h>
- X
- Xextern char *strtok();
- Xextern char *strchr();
- Xextern void closelog();
- X
- X/* Local stuff. */
- X
- X#include "log_tcp.h"
- X
- X/* List of functions that implement the options. Add yours here. */
- X
- Xstatic void user_option(); /* execute "user=name" option */
- Xstatic void group_option(); /* execute "group=name" option */
- Xstatic void umask_option(); /* execute "umask=mask" option */
- Xstatic void twist_option(); /* execute "twist=command" option */
- X#ifdef RFC931_OPTION
- Xstatic void rfc931_option(); /* execute "rfc931" option */
- X#endif
- Xstatic void setenv_option(); /* execute "setenv=name value" */
- X
- Xstatic char *chop_string(); /* strip leading and trailing blanks */
- X
- X/* Structure of the options table. */
- X
- Xstruct option {
- X char *name; /* keyword name, case does not matter */
- X int need_value; /* value required or not */
- X void (*func) (); /* function that does the real work */
- X};
- X
- X/* List of known keywords. Add yours here. */
- X
- Xstatic struct option option_table[] = {
- X "user", 1, user_option, /* switch user id */
- X "group", 1, group_option, /* switch group id */
- X "umask", 1, umask_option, /* change umask */
- X "spawn", 1, shell_cmd, /* spawn shell command */
- X "twist", 1, twist_option, /* replace current process */
- X#ifdef RFC931_OPTION
- X "rfc931", 0, rfc931_option, /* do RFC 931 lookup */
- X#endif
- X "setenv", 1, setenv_option, /* update environment */
- X 0,
- X};
- X
- Xstatic char whitespace[] = " \t\r\n";
- X
- X/* process_options - process optional access control information */
- X
- Xprocess_options(options, daemon, client)
- Xchar *options;
- Xchar *daemon;
- Xstruct from_host *client;
- X{
- X char *key;
- X char *value;
- X struct option *op;
- X
- X /*
- X * Light-weight parser. Remember, we may be running as root so we need
- X * code that is easy to comprehend.
- X */
- X
- X for (key = strtok(options, ":"); key; key = strtok((char *) 0, ":")) {
- X if (value = strchr(key, '=')) { /* keyword=value */
- X *value++ = 0;
- X value = chop_string(value); /* strip blanks around value */
- X if (*value == 0)
- X value = 0; /* no value left */
- X }
- X key = chop_string(key); /* strip blanks around key */
- X for (op = option_table; op->name; op++) /* find keyword */
- X if (strcasecmp(op->name, key) == 0)
- X break;
- X if (op->name == 0) {
- X syslog(LOG_ERR, "bad option or syntax: \"%s\"", key);
- X } else if (value == 0 && op->need_value) {
- X syslog(LOG_ERR, "option \"%s\" requires value", key);
- X } else if (value && op->need_value == 0) {
- X syslog(LOG_ERR, "option \"%s\" requires no value", key);
- X } else {
- X (*(op->func)) (value, daemon, client);
- X }
- X }
- X}
- X
- X/* user_option - switch user id */
- X
- X/* ARGSUSED */
- X
- Xstatic void user_option(value, daemon, client)
- Xchar *value;
- Xchar *daemon;
- Xstruct from_host *client;
- X{
- X struct passwd *pwd;
- X struct passwd *getpwnam();
- X
- X if ((pwd = getpwnam(value)) == 0) {
- X syslog(LOG_ERR, "unknown user: \"%s\"", value);
- X clean_exit(client);
- X } else if (setuid(pwd->pw_uid)) {
- X syslog(LOG_ERR, "setuid(%s): %m", value);
- X clean_exit(client);
- X }
- X}
- X
- X/* group_option - switch group id */
- X
- X/* ARGSUSED */
- X
- Xstatic void group_option(value, daemon, client)
- Xchar *value;
- Xchar *daemon;
- Xstruct from_host *client;
- X{
- X struct group *grp;
- X struct group *getgrnam();
- X
- X if ((grp = getgrnam(value)) == 0) {
- X syslog(LOG_ERR, "unknown group: \"%s\"", value);
- X clean_exit(client);
- X } else if (setgid(grp->gr_gid)) {
- X syslog(LOG_ERR, "setgid(%s): %m", value);
- X clean_exit(client);
- X }
- X}
- X
- X/* umask_option - set file creation mask */
- X
- X/* ARGSUSED */
- X
- Xstatic void umask_option(value, daemon, client)
- Xchar *value;
- Xchar *daemon;
- Xstruct from_host *client;
- X{
- X unsigned mask;
- X char junk;
- X
- X if (sscanf(value, "%o%c", &mask, &junk) != 1 || (mask & 0777) != mask) {
- X syslog(LOG_ERR, "bad umask: \"%s\"", value);
- X clean_exit(client);
- X }
- X (void) umask(mask);
- X}
- X
- X/* twist_option - replace process by shell command */
- X
- Xstatic void twist_option(value, daemon, client)
- Xchar *value;
- Xchar *daemon;
- Xstruct from_host *client;
- X{
- X char buf[BUFSIZ];
- X int pid = getpid();
- X char *error;
- X
- X percent_x(buf, sizeof(buf), value, daemon, client, pid);
- X
- X /* Since we will not be logging in the usual way, do it here and now. */
- X
- X syslog(SEVERITY, "twist from %s to %s", hosts_info(client), buf);
- X closelog();
- X
- X /*
- X * Before switching to the shell, set up stdout and stderr in case the
- X * Ultrix inetd didn't.
- X */
- X
- X (void) close(1);
- X (void) close(2);
- X if (dup(0) != 1 || dup(0) != 2) {
- X error = "dup: %m";
- X } else {
- X (void) execl("/bin/sh", "sh", "-c", buf, (char *) 0);
- X error = "/bin/sh: %m";
- X }
- X
- X /* Can get here only in case of errors. */
- X
- X#ifdef LOG_MAIL
- X (void) openlog(daemon, LOG_PID, FACILITY);
- X#else
- X (void) openlog(daemon, LOG_PID);
- X#endif
- X syslog(LOG_ERR, error);
- X clean_exit(client);
- X}
- X
- X#ifdef RFC931_OPTION
- X
- X/* rfc931_option - look up remote user name */
- X
- X/* ARGSUSED */
- X
- Xstatic void rfc931_option(value, daemon, client)
- Xchar *value;
- Xchar *daemon;
- Xstruct from_host *client;
- X{
- X if (client->sock_type == FROM_CONNECTED) {
- X if (client->sin == 0) {
- X syslog(LOG_ERR, "no socket info for username lookup");
- X } else {
- X client->user = rfc931_name(client->sin);
- X }
- X }
- X}
- X
- X#endif
- X
- X/* setenv_option - set environment variable */
- X
- X/* ARGSUSED */
- X
- Xstatic void setenv_option(value, daemon, client)
- Xchar *value;
- Xchar *daemon;
- Xstruct from_host *client;
- X{
- X char *var_name;
- X char *var_value;
- X char buf[BUFSIZ];
- X int pid;
- X
- X /*
- X * What we get is one string with the name and the value separated by
- X * whitespace. Find the end of the name. If that is also the end of the
- X * string, the value is empty.
- X */
- X
- X var_value = value + strcspn(value, whitespace);
- X
- X if (*var_value == 0) { /* just a name, that's all */
- X var_name = value;
- X } else { /* expand %stuff in value */
- X *var_value++ = 0;
- X var_name = chop_string(value);
- X pid = getpid();
- X percent_x(buf, sizeof(buf), var_value, daemon, client, pid);
- X var_value = chop_string(buf);
- X }
- X if (setenv(var_name, var_value, 1)) {
- X syslog(LOG_ERR, "memory allocation failure");
- X clean_exit(client);
- X }
- X}
- X
- X/* chop_string - strip leading and trailing blanks from string */
- X
- Xstatic char *chop_string(start)
- Xregister char *start;
- X{
- X register char *end;
- X
- X while (*start && isspace(*start))
- X start++;
- X
- X for (end = start + strlen(start); end > start && isspace(end[-1]); end--)
- X /* void */ ;
- X *end = 0;
- X
- X return (start);
- X}
- END_OF_options.c
- if test 10084 -ne `wc -c <options.c`; then
- echo shar: \"options.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f clean_exit.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"clean_exit.c\"
- else
- echo shar: Extracting \"clean_exit.c\" \(1268 characters\)
- sed "s/^X//" >clean_exit.c <<'END_OF_clean_exit.c'
- X /*
- X * clean_exit() cleans up and terminates the program. It should be called
- X * instead of exit when for some reason the real network daemon will not or
- X * cannot be run. Reason: in the case of a datagram-oriented service we must
- X * discard the not-yet received data from the client. Otherwise, inetd will
- X * see the same datagram again and again, and go into a loop.
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) clean_exit.c 1.1 92/06/11 22:21:52";
- X#endif
- X
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <stdio.h>
- X
- Xextern void exit();
- X
- X#include "log_tcp.h"
- X
- X/* clean_exit - clean up and exit */
- X
- Xvoid clean_exit(client)
- Xstruct from_host *client;
- X{
- X char buf[BUFSIZ];
- X struct sockaddr sa;
- X int size = sizeof(sa);
- X
- X /*
- X * Eat up the not-yet received packet. Some systems insist on a non-zero
- X * source address argument in the recvfrom() call below.
- X */
- X
- X if (client->sock_type == FROM_UNCONNECTED)
- X (void) recvfrom(0, buf, sizeof(buf), 0, &sa, &size);
- X
- X /*
- X * Be kind to the inetd. We already reported the problem via the syslogd,
- X * and there is no need for additional garbage in the logfile.
- X */
- X
- X exit(0);
- X}
- END_OF_clean_exit.c
- if test 1268 -ne `wc -c <clean_exit.c`; then
- echo shar: \"clean_exit.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f setenv.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"setenv.c\"
- else
- echo shar: Extracting \"setenv.c\" \(931 characters\)
- sed "s/^X//" >setenv.c <<'END_OF_setenv.c'
- X /*
- X * Some systems do not have setenv(). This one is modeled after 4.4 BSD, but
- X * is implemented in terms of portable primitives only: getenv(), putenv()
- X * and malloc(). It should therefore be safe to use on every UNIX system.
- X *
- X * If clobber == 0, do not overwrite an existing variable.
- X *
- X * Returns nonzero if memory allocation fails.
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) setenv.c 1.1 93/03/07 22:47:58";
- X#endif
- X
- X/* setenv - update or insert environment (name,value) pair */
- X
- Xint setenv(name, value, clobber)
- Xchar *name;
- Xchar *value;
- Xint clobber;
- X{
- X char *malloc();
- X char *getenv();
- X char *cp;
- X
- X if (clobber == 0 && getenv(name) != 0)
- X return (0);
- X if ((cp = malloc(strlen(name) + strlen(value) + 2)) == 0)
- X return (1);
- X sprintf(cp, "%s=%s", name, value);
- X return (putenv(cp));
- X}
- END_OF_setenv.c
- if test 931 -ne `wc -c <setenv.c`; then
- echo shar: \"setenv.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f patchlevel.h -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"patchlevel.h\"
- else
- echo shar: Extracting \"patchlevel.h\" \(70 characters\)
- sed "s/^X//" >patchlevel.h <<'END_OF_patchlevel.h'
- X#ifndef lint
- Xstatic char patchlevel[] = "@(#) patchlevel 5.1";
- X#endif
- END_OF_patchlevel.h
- if test 70 -ne `wc -c <patchlevel.h`; then
- echo shar: \"patchlevel.h\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f strtok.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"strtok.c\"
- else
- echo shar: Extracting \"strtok.c\" \(2976 characters\)
- sed "s/^X//" >strtok.c <<'END_OF_strtok.c'
- X/*
- X * Copyright (c) 1988 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms, with or without
- X * modification, are permitted provided that the following conditions
- X * are met:
- X * 1. Redistributions of source code must retain the above copyright
- X * notice, this list of conditions and the following disclaimer.
- X * 2. Redistributions in binary form must reproduce the above copyright
- X * notice, this list of conditions and the following disclaimer in the
- X * documentation and/or other materials provided with the distribution.
- X * 3. All advertising materials mentioning features or use of this software
- X * must display the following acknowledgement:
- X * This product includes software developed by the University of
- X * California, Berkeley and its contributors.
- X * 4. Neither the name of the University nor the names of its contributors
- X * may be used to endorse or promote products derived from this software
- X * without specific prior written permission.
- X *
- X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- X * SUCH DAMAGE.
- X */
- X
- X#if defined(LIBC_SCCS) && !defined(lint)
- Xstatic char sccsid[] = "@(#)strtok.c 5.8 (Berkeley) 2/24/91";
- X#endif /* LIBC_SCCS and not lint */
- X
- X#ifdef __STDC__ /* Added for backwards compatibility -- WZV 930122 */
- X#include <stddef.h>
- X#include <string.h>
- X#else
- X#define const
- X#define NULL 0
- X#endif
- X
- Xchar *
- Xstrtok(s, delim)
- X register char *s;
- X register const char *delim;
- X{
- X register char *spanp;
- X register int c, sc;
- X char *tok;
- X static char *last;
- X
- X
- X if (s == NULL && (s = last) == NULL)
- X return (NULL);
- X
- X /*
- X * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
- X */
- Xcont:
- X c = *s++;
- X for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
- X if (c == sc)
- X goto cont;
- X }
- X
- X if (c == 0) { /* no non-delimiter characters */
- X last = NULL;
- X return (NULL);
- X }
- X tok = s - 1;
- X
- X /*
- X * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
- X * Note that delim must have one NUL; we stop if we see that, too.
- X */
- X for (;;) {
- X c = *s++;
- X spanp = (char *)delim;
- X do {
- X if ((sc = *spanp++) == c) {
- X if (c == 0)
- X s = NULL;
- X else
- X s[-1] = 0;
- X last = s;
- X return (tok);
- X }
- X } while (sc != 0);
- X }
- X /* NOTREACHED */
- X}
- END_OF_strtok.c
- if test 2976 -ne `wc -c <strtok.c`; then
- echo shar: \"strtok.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f fix_options.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"fix_options.c\"
- else
- echo shar: Extracting \"fix_options.c\" \(1315 characters\)
- sed "s/^X//" >fix_options.c <<'END_OF_fix_options.c'
- X /*
- X * Routine to disable IP-level socket options. This code was taken from 4.4BSD
- X * rlogind source, but all mistakes in it are my fault.
- X *
- X * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- X */
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) fix_options.c 1.1 93/03/07 22:48:02";
- X#endif
- X
- X#include <sys/types.h>
- X#include <sys/param.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <stdio.h>
- X#include <syslog.h>
- X
- X#include "log_tcp.h"
- X
- X/* fix_options - get rid of IP-level socket options */
- X
- Xfix_options(client)
- Xstruct from_host *client;
- X{
- X#ifdef IP_OPTIONS
- X unsigned char optbuf[BUFSIZ / 3], *cp;
- X char lbuf[BUFSIZ], *lp;
- X int optsize = sizeof(optbuf), ipproto;
- X struct protoent *ip;
- X
- X if ((ip = getprotobyname("ip")) != 0)
- X ipproto = ip->p_proto;
- X else
- X ipproto = IPPROTO_IP;
- X
- X if (getsockopt(0, ipproto, IP_OPTIONS, (char *) optbuf, &optsize) == 0
- X && optsize != 0) {
- X lp = lbuf;
- X for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
- X sprintf(lp, " %2.2x", *cp);
- X syslog(LOG_NOTICE,
- X "connect from %s with IP options (ignored):%s",
- X hosts_info(client), lbuf);
- X if (setsockopt(0, ipproto, IP_OPTIONS, (char *) 0, optsize) != 0) {
- X syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");
- X clean_exit(client);
- X }
- X }
- X#endif
- X}
- END_OF_fix_options.c
- if test 1315 -ne `wc -c <fix_options.c`; then
- echo shar: \"fix_options.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f inet_addr_fix -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"inet_addr_fix\"
- else
- echo shar: Extracting \"inet_addr_fix\" \(552 characters\)
- sed "s/^X//" >inet_addr_fix <<'END_OF_inet_addr_fix'
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) inet_addr_fix 1.1 93/03/07 22:48:04";
- X#endif
- X
- X /*
- X * Some inet_addr() versions return a struct/union instead of a long. You
- X * have this problem when the compiler complains about illegal lvalues or
- X * something like that. The following code fixes this mutant behaviour.
- X *
- X * Bug reported by ben@piglet.cr.usgs.gov (Rev. Ben A. Mesander).
- X */
- X
- Xstatic long fix_inet_addr(string)
- Xchar *string;
- X{
- X struct in_addr addr = inet_addr(string);
- X
- X return (addr.s_addr);
- X}
- X
- X#define inet_addr fix_inet_addr
- END_OF_inet_addr_fix
- if test 552 -ne `wc -c <inet_addr_fix`; then
- echo shar: \"inet_addr_fix\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of shell archive.
- exit 0
-
-